Compare commits

...
170 Commits
Author SHA1 Message Date
Nassim Jahnke 7a0ec492d1 5.4.0 Release 2025-06-20 19:26:25 +02:00
Nassim Jahnke b4fac61eb9 Fix tinted leaves particle reading in 1.21.6 type 2025-06-20 19:26:19 +02:00
Nassim Jahnke 7817b7a422 Remove snapshot version 2025-06-17 02:14:13 +02:00
Nassim Jahnke ed266d296e 1.21.6-rc1 2025-06-17 02:13:06 +02:00
Nassim Jahnke 3ce324c1e1 1.21.6-pre4 2025-06-17 02:13:06 +02:00
Nassim Jahnke 835dc4733d 1.21.6-pre3 2025-06-17 02:13:06 +02:00
Nassim Jahnke aa66a6b482 1.21.6-pre2 2025-06-17 02:13:05 +02:00
Nassim Jahnke 406855d427 1.21.6-pre1 2025-06-17 02:13:05 +02:00
Nassim Jahnke fe5ba84f7a 25w21a 2025-06-17 02:13:05 +02:00
Nassim Jahnke f49495162b Use updated versioned types 2025-06-17 02:13:05 +02:00
Nassim Jahnke be5c451f42 25w20a 2025-06-17 02:13:05 +02:00
Nassim Jahnke 1517596a9f Add hashed item handling 2025-06-17 02:13:05 +02:00
Nassim Jahnke 6a89b84879 Fix attribute modifier writing 2025-06-17 02:13:05 +02:00
Nassim Jahnke c414458f1c 25w19a 2025-06-17 02:13:05 +02:00
Nassim Jahnke ec9086abc4 25w18a 2025-06-17 02:13:05 +02:00
Nassim Jahnke d6c16677fc 25w17a 2025-06-17 02:13:05 +02:00
Nassim Jahnke 7cd3a75ef8 Handle player_command change 2025-06-17 02:13:05 +02:00
Nassim Jahnke 0677cbaa3c 25w16a 2025-06-17 02:13:05 +02:00
Nassim Jahnke ab8b5abc48 25w15a
Is it 1.22? Is it 1.21.6? Who knows
2025-06-17 02:13:05 +02:00
FlorianMichael 60c67659d0 Filter invalid characters in command click events in 1.21.4->.5 (#4528)
Minecraft versions prior to 1.21.4 filter out invalid characters when handling the click event on the clientside while 1.21.5+ validates and throws in the network codec per ExtraCodecs#CHAT_STRING
2025-06-15 12:28:08 +02:00
dewgsandFlorianMichael 814190c2df Add missing dimension change checks for entity tracking (#4527)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-06-14 17:29:40 +02:00
RK_01 04d647bfef Fix respawning with 1.21.2+ clients on older vanilla servers (#4509) 2025-06-12 18:18:37 +02:00
FlorianMichael 930bf67229 Don't always send player inputs on Fabric servers in 1.21->1.21.2 (#4523) 2025-06-11 02:52:21 +02:00
FlorianMichael 51c3085180 Validate tag identifiers in block predicates in 1.20.3->1.20.5 (#4522)
As usual, versions <= 1.20.4 have the entire parsing code in a try catch block while 1.20.5+ needs valid data.

Closes https://github.com/ViaVersion/ViaVersion/issues/4515
2025-06-09 15:08:00 +02:00
FlorianMichael b981223e0a Make workflows manual runnable (#4521) 2025-06-08 23:56:14 +02:00
FlorianMichael 3951cff03a Cancel out unmapped (block) ids in HolderSetImpl (#4512)
In VB, mapping data will return -1 for missing block ids (which is for almost all blocks the case). This is made so that VV rewriters can cancel these blocks away nicely (as mostly used in places where it's better to show the user nothing rather than wrong blocks, such as statistics).

Fixes https://github.com/ViaVersion/ViaVersion/issues/4510
2025-05-28 07:41:21 +02:00
Nassim Jahnke 77a6ae37c0 Fix game profile null id hashing
Fixes #4506
2025-05-27 15:28:35 +02:00
Nassim Jahnke 12e201633f Fix rabbit variant hashing 2025-05-27 14:28:04 +02:00
Nassim Jahnke 8eb005e775 Fix tropical fish pattern hashing 2025-05-27 14:05:40 +02:00
RK_01 4d39c0007f Add QoL API for GameProfile (#4505) 2025-05-27 08:39:08 +02:00
FlorianMichael d9609e60b8 Don't fail on book pages rewrite in 1.8->1.9 as per Vanilla behaviour (#4504) 2025-05-26 20:22:29 +02:00
Nassim Jahnke ab3927dff7 Implement our own hash writing
This avoids a lot of indirection, wrapping/boxing and data copying while also making sure we can immediately implement them on new snapshots without waiting for a separate (also ever-growing) library.

The HashBuilder is partially copied from MCStructs, everything else was built anew to intentionally stay away from Vanilla's Codec design
2025-05-26 12:37:58 +02:00
FlorianMichael 1a60c52fa3 Don't convert creative-slot-lock/map-post-processing in 1.20.3->.5 (#4500) 2025-05-22 21:38:18 +02:00
github-actions[bot]andgradle-update-robot f88dae1828 Update Gradle Wrapper from 8.14 to 8.14.1 (#4501)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-05-22 17:35:05 +02:00
Nassim JahnkeandFlorianMichael 2626773267 Refactor 1.20.5+ versioned types
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-05-17 15:12:52 +02:00
Nassim Jahnke f16f1905b7 Move container handling into handleShowItem directly
Fixes ViaVersion/ViaBackwards#1010
2025-05-15 11:08:44 +02:00
Nassim Jahnke cc435b2b02 Move item id setter below backup method 2025-05-14 14:01:03 +02:00
Nassim Jahnke eb2d603aae Add protected handleRewritablesToServer method 2025-05-14 13:29:40 +02:00
Nassim Jahnke c30e0f45bc Split up item rewriter methods even more
Item backups and its restoration processes have to be more carefully placed around Rewritable handling, so the original/restored data stays untouched
2025-05-14 13:22:32 +02:00
Nassim Jahnke ebb24c73a2 Don't call super handleItemToClient with custom item hasher 2025-05-13 23:12:06 +02:00
Nassim Jahnke 575c5b9abf Move restoreBackupData call up 2025-05-13 22:55:46 +02:00
Nassim Jahnke 812694d74d Split updateItemDataComponents in two 2025-05-13 22:45:25 +02:00
Nassim Jahnke 1efaffbc7d Implement more data conversion
Most importantly attributes
2025-05-12 18:59:41 +02:00
FlorianMichael b03b5f7da7 [ci skip] Make the runViaProxy task work with Gradle's configuration cache (#4483) 2025-05-12 17:53:54 +02:00
Nassim Jahnke 3554db9e3a Prepare for hashed item rewriting 2025-05-11 23:10:20 +02:00
Nassim Jahnke a6d58fc02b Only track item when necessary, cleanup 2025-05-11 23:10:18 +02:00
RaphiMC e2045295a0 Hash item data components in 1.21.4->1.21.5 2025-05-11 23:10:17 +02:00
FlorianMichael a6b219c0df [ci skip] Allow build if Git is not installed or the project is downloaded as code zip (#4477) 2025-05-11 22:26:35 +02:00
FlorianMichael 0b5721d81e Check for non-negative value for damage & repair cost in 1.20.3->.5 (#4491)
In 1.20.5, codecs introduced the non-negative int type which will fail if a value <= 0 is present. In 1.20.4, Mojang gracefully handled negative values

Fixes https://github.com/ViaVersion/ViaFabricPlus/issues/763
2025-05-11 22:05:59 +02:00
FlorianMichael 5bad61e210 Don't perform length validation on zero bit storage in 1.18 palette type (#4479)
Minecraft has its own ZeroBitStorage type for this case so we don't need to perform the validation, also removed the comments as this is just how our code should work to match Vanilla behaviour (at least for the first one; I did not verify the readValues code)

Closes https://github.com/ViaVersion/ViaVersion/issues/4476
2025-05-05 21:06:37 +02:00
FlorianMichael e597d8faaa [ci skip] Include platform launcher runtime dependency for tests (#4474) 2025-04-29 10:21:30 +02:00
FelixandFlorianMichael d9eb7109bd Add missing PLAYER_CHAT handlers in 1.20/1.21 versions (#4472)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-04-28 11:57:10 +02:00
github-actions[bot]andgradle-update-robot 77d68306b6 Update Gradle Wrapper from 8.13 to 8.14 (#4471)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-04-26 16:33:53 +02:00
FlorianMichael 16aec9c0a1 Fix legacy item/entity hover event + potion id in 1.21.4->1.21.5 (#4469) 2025-04-23 20:52:53 +02:00
FlorianMichael c6cde5fc10 Cancel unknown block entities in BlockRewriter#registerBlockEntityData (#4466) 2025-04-22 16:05:44 +02:00
Nassim Jahnke bf84eb0141 Add separate config option for text component conversion errors 2025-04-20 15:57:22 +02:00
Nassim Jahnke 4dfc3bd2be Make parts of item data component rewriting more generic via an interface 2025-04-16 10:59:20 +02:00
Nassim Jahnke b0c53ffdd3 Make helper method in Copyable static 2025-04-15 21:20:57 +02:00
Nassim Jahnke d65b2abc46 Ignore invalid data in signs 2025-04-15 20:46:13 +02:00
Nassim Jahnke 03313a1681 Catch text conversion errors 2025-04-15 10:02:00 +02:00
Nassim Jahnke 78c5e2c8e3 Convert hover events to legacy deep 2025-04-14 08:57:04 +02:00
FlorianMichael e467c7c03f Set correct data types in 1.8->1.9 CONTAINER_CLICK (#4460) 2025-04-14 08:55:45 +02:00
Nassim Jahnke 0c01425641 5.3.2 Release 2025-04-13 15:45:15 +02:00
Nassim Jahnke 01d26e7ac5 Make trimStrings public 2025-04-12 15:37:19 +02:00
Nassim Jahnke 99ea6c32ad Add client and server protocol to informative exception data 2025-04-11 22:20:38 +02:00
Nassim Jahnke cf231d92b1 Update mcstructs
Fixes ViaVersion/ViaBackwards#988
2025-04-10 18:58:23 +02:00
FlorianMichael f555188428 [ci skip] Print correct max read length in StringType sanity checks (#4456) 2025-04-10 16:16:46 +02:00
FlorianMichael 93d6fa2e78 Only add (block) entity id if needed for tooltips in 1.20.3->.5 2025-04-09 17:22:33 +02:00
Nassim Jahnke 162fcafb36 Ignore unknown entity data too in 1.20.3->1.20.5
Fixes #4433
Closes #4451
2025-04-09 16:24:03 +02:00
FlorianMichael 3d0a0fe590 Send player input every tick when in boat in 1.21->1.21.2 (#4449) 2025-04-09 16:14:07 +02:00
bookyandFlorianMichael b06556a84e Fix advancement menu background keys (#4454)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-04-09 15:56:06 +02:00
Nassim Jahnke ac8bb104b3 Fix primitive array copying 2025-04-08 15:54:02 +02:00
FlorianMichael 4b85ca7691 Fix handling of removed item components in 1.20.3->.5 component rewriter (#4452)
Only relevant for VB though as VV will never put empty structured data through it.
2025-04-08 15:34:30 +02:00
FlorianMichael ebd8eb79c1 Use correct version in json to tag conversion in 1.21.4->.5 (#4450) 2025-04-08 15:32:07 +02:00
Nassim Jahnke 09cffbfb33 Null check connection in Velocity connect listener 2025-04-05 18:35:24 +02:00
FlorianMichael 49a1bffc98 Only send the connection details if ViaVersion is active (#4434) 2025-04-05 11:54:06 +02:00
FlorianMichael da022a0b63 [ci skip] Fix ItemRewriter#registerContainerClick1_21_5 data order (#4435) 2025-04-05 11:53:36 +02:00
Nassim Jahnke 3beddaf522 Move show item container contents conversion to the right place
Fixes #4444
2025-04-05 11:53:08 +02:00
Nassim Jahnke 70139c6838 Bump version to 5.3.2-SNAPSHOT 2025-04-05 11:52:24 +02:00
Nassim Jahnke f040077c13 5.3.1 Release 2025-03-30 21:07:54 +02:00
Nassim Jahnke 1f404820b7 Track it on 1.21.4 servers already 2025-03-30 18:51:03 +02:00
Nassim Jahnke 742e70fff6 Small cleanup, track gamemode 2025-03-30 18:26:05 +02:00
Nassim Jahnke dd6a1a7f6e Update old version warning to <1.16 servers
The original <1.13 warning was added almost 5 years ago, since then more small issues have come up from newer clients having fundamental changes and server stats on those old versions have dropped even more. That said, ViaVersion will keep working on these servers presumably forever
2025-03-30 16:02:27 +02:00
Nassim Jahnke 08ef7c2f35 Add back legacy hover event conversion 2025-03-30 15:05:03 +02:00
Gero e128469313 Fix missing mapping of CHUNKS_BIOMES for 1.21.5 (#4425) 2025-03-30 11:56:29 +02:00
FlorianMichael cbb753271e [ci skip] Update repository declaration in GH workflow (#4424) 2025-03-29 20:28:41 +01:00
FlorianMichael 29f299d882 Update MCStructs to 3.0.0 (#4422) 2025-03-29 14:30:06 +01:00
Pablo Herrera 41138aabd1 Implement pick-block for legacy servers (#4412) 2025-03-29 13:07:44 +01:00
Nassim Jahnke b90f20cfeb Fix 1.20.3 disguised chat handler 2025-03-29 10:15:21 +01:00
Nassim Jahnke 585028beb7 Bump version to 5.3.1-SNAPSHOT 2025-03-29 10:14:45 +01:00
Nassim Jahnke 160eaa35aa 5.3.0 Release 2025-03-28 17:06:08 +01:00
Nassim Jahnke 9fb02581a6 Also check for hanging sign block entities 2025-03-28 17:04:59 +01:00
FlorianMichael 7d01d5363b Add TagUtil#getNamespacedTagKey and simplify code in component rewriter 2025-03-28 14:37:00 +01:00
Nassim Jahnke 8a549d7f11 And for disguised chat params 2025-03-28 14:12:41 +01:00
Nassim Jahnke 50e2db93b4 Also update name and target name 2025-03-28 14:12:41 +01:00
Nassim Jahnke 2d80c9526a Also process unsigned signed player chat 2025-03-28 14:12:41 +01:00
Nassim Jahnke 80d72121cf Check for horse saddles in entity data too 2025-03-28 14:12:41 +01:00
Nassim Jahnke ba11b3c214 Remove show_in_tooltip 2025-03-28 14:12:41 +01:00
Nassim Jahnke 2ee4c86dcb Remote snapshot version 2025-03-28 14:12:41 +01:00
Nassim Jahnke 97b8cbbc6f 1.21.5-rc2 2025-03-28 14:12:40 +01:00
riku6460 1a1ae41a7b Fix blockEntityHandler not being called when mappedId == id 2025-03-28 14:12:40 +01:00
Nassim Jahnke 2b7a86bc55 Play shield break and block sounds from entity events 2025-03-28 14:12:40 +01:00
Nassim Jahnke 175c320389 Simplify server container desync check with Paper API if present
Fixes desyncs on item drags due to missing item data for 1.21.5+ clients
2025-03-28 14:12:40 +01:00
RK_01 b22430a923 Moved hashed item conversion code into method (#16)
Allows for easy injection in platforms like ViaProxy or ViaFabricPlus
2025-03-28 14:12:40 +01:00
Nassim Jahnke c9f9e88ebe 1.21.5-rc1 2025-03-28 14:12:40 +01:00
Nassim Jahnke 7f0b3fc241 1.21.5-pre3 2025-03-28 14:12:39 +01:00
RK_01 e13b99e73a Use new blocks_attacks component for 1.8 sword blocking (#15) 2025-03-28 14:12:39 +01:00
Nassim Jahnke 304d9f04ec Send saddle equipment for pigs and striders 2025-03-28 14:12:39 +01:00
Nassim Jahnke 92b59fd904 Update dependencies 2025-03-28 14:12:39 +01:00
Nassim Jahnke 7e42ce2a5c 1.21.5-pre2 2025-03-28 14:12:39 +01:00
Nassim Jahnke d3475dc751 Fix pig saddle index 2025-03-28 14:12:39 +01:00
Nassim Jahnke cd6e5a3d7a 1.21.5-pre1 2025-03-28 14:12:38 +01:00
Nassim Jahnke 67e50ed6f4 Add missing provides_banner_patterns item data, fix entity variants 2025-03-28 14:12:38 +01:00
Nassim Jahnke 097ad1c721 Add helper methods for removing data components 2025-03-28 14:12:38 +01:00
FlorianMichael 6a4f5732e2 Handle show_in_tooltip values in chat item components 2025-03-28 14:12:38 +01:00
Nassim Jahnke 000769e7c5 Adventure mode predicate changes
🫠
2025-03-28 14:12:38 +01:00
Nassim Jahnke c725242713 Fix block entity removal OOB 2025-03-28 14:12:37 +01:00
Nassim Jahnke fd9d7d674b 25w10a 2025-03-28 14:12:37 +01:00
Nassim Jahnke 5c87388353 Update mappings 2025-03-28 14:12:37 +01:00
Nassim Jahnke 3b65720d04 Update ViaNBT 2025-03-28 14:12:37 +01:00
Nassim Jahnke 44af621c12 25w09b 2025-03-28 14:12:37 +01:00
Nassim Jahnke 4e33615d9e Update sign text 2025-03-28 14:12:37 +01:00
Nassim Jahnke a5b34b9fac 25w09a 2025-03-28 14:12:37 +01:00
Nassim Jahnke 674b81a5ce 25w08a 2025-03-28 14:12:36 +01:00
Nassim Jahnke 36a3a7bd32 Fix read of single value storage 2025-03-28 14:12:36 +01:00
Nassim Jahnke d2b2f56438 25w07a 2025-03-28 14:12:36 +01:00
Nassim Jahnke 5cb147f8c5 25w06a 2025-03-28 14:12:36 +01:00
Nassim Jahnke c1c6d7378d Fix optional holder type 2025-03-28 14:12:36 +01:00
Nassim Jahnke 3cd9d8c20b 25w05a 2025-03-28 14:12:35 +01:00
Nassim Jahnke 8faa00af14 Finish up things 2025-03-28 14:12:35 +01:00
Nassim Jahnke 2aa02cfc20 Mostly finished 25w04a 2025-03-28 14:12:35 +01:00
Nassim Jahnke 1071e68e6e Update show_text value key 2025-03-28 14:12:35 +01:00
Nassim Jahnke bcf4efacc5 Remove block entities if mapped to nothing 2025-03-28 14:12:35 +01:00
Nassim Jahnke 4ab3148dd9 25w03a 2025-03-28 14:12:34 +01:00
Nassim Jahnke b0269b53b7 Offset pig variant entity data type 2025-03-28 14:12:34 +01:00
Nassim Jahnke 5df2ffe6a8 Handle hover and click event changes
Changes to the component rewriter will be done in the public branch
2025-03-28 14:12:34 +01:00
Nassim Jahnke 0e8e58dc5c WIP 25w02a 2025-03-28 14:12:34 +01:00
FlorianMichael d1e27617a9 Update warning when no working pipe is found (#4416) 2025-03-26 21:24:19 +01:00
FlorianMichael 5ab4f49148 Add Copyable interface and unify copy() methods (#4413) 2025-03-25 16:37:00 +01:00
FlorianMichael 494da63b66 Rewrite ConnectionManager to track client/server connections (#4410) 2025-03-12 16:51:34 +01:00
Nassim Jahnke a0b0ed4b68 Make <1.21.2 container id types consistent with Vanilla again
... that's to say, to make them inconsistent thanks to special ids:
Byte:
- CONTAINER_SET_SLOT
- CONTAINER_CLICK
- PLACE_GHOST_RECIPE
- PLACE_RECIPE
- CONTAINER_BUTTON_CLICK
- CONTAINER_CLOSE (serverbound)
- CONTAINER_ACK (serverbound)
Unsigned byte (unchanged):
- OPEN_SCREEN
- CONTAINER_SET_CONTENT
- CONTAINER_SET_DATA
- HORSE_SCREEN_OPEN
- CONTAINER_CLOSE (clientbound)
- CONTAINER_ACK (clientbound)
Short (unchanged):
- SET_CREATIVE_MODE_SLOT

This doesn't change much in practice, but means it matches the Vanilla reading
2025-03-11 10:36:49 +01:00
FlorianMichael e9ec29a217 Javadoc fixes (#4391) 2025-03-08 15:21:24 +01:00
FlorianMichaelandNassim Jahnke fb5bc8254a Add connection details protocol implementation (#4371)
Adds an optional custom payload protocol which platforms can use to communicate the native version of users across backend servers, the current implementation supports Velocity by sending the player's native version to the backend servers. Platforms may call ConnectionDetails#sendConnectionDetails themselves to ensure the packet getting handled by the server.

Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2025-03-04 15:54:37 +01:00
FlorianMichael a7bc03f6a9 Treat changes in client bound base protocol handlers as separate protocols (#4400) 2025-02-27 22:31:35 +01:00
github-actions[bot]andgradle-update-robot d1bea0326c Update Gradle Wrapper from 8.12.1 to 8.13 (#4396)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-02-25 18:40:57 +01:00
Nassim Jahnke d3512c9e7f Check overrides too when removing item data 2025-02-25 13:42:52 +01:00
Nassim Jahnke 2f1f7538e5 Ignore invalid ingredients in registry data 2025-02-23 11:10:04 +01:00
FlorianMichael ac3362f950 Don't add damage types twice in 1.19.4->1.20 (#4389)
Closes https://github.com/ViaVersion/ViaFabricPlus/issues/652
2025-02-19 14:13:52 +01:00
FlorianMichael 74e510b056 Fix clientEntityId check in MovementTransmitterProvider (#4390) 2025-02-19 14:13:24 +01:00
FlorianMichael fdd263b806 Make functions optional which are not always required in ViaPlatform (#4370) 2025-02-16 13:56:32 +01:00
FlorianMichael a764cec4a9 Add DebugHandler#logPrePacketTransform/setLogPacketTransform (#4386) 2025-02-16 13:55:20 +01:00
FlorianMichael 764861e29b [ci skip] Migrate the user wiki to GitHub (#4382) 2025-02-10 15:37:14 +01:00
EnZaXD 3e946ff67e Add user feedback to /viaversion list & player if no players are found (#4369) 2025-01-31 22:36:39 +01:00
Nassim Jahnke dca45ceb0e Simplify read error 2025-01-30 17:13:12 +01:00
Florian 327ec23ae9 Add PacketTypeMap#ofUnsequenced helper function (#4368) 2025-01-30 13:51:10 +01:00
Florian 9cf7737502 Fix container hover event deserialization (#4365) 2025-01-29 15:37:38 +01:00
Florian 0c5fa1b00a Add ProtocolRunnable internal API (#4364) 2025-01-29 15:36:57 +01:00
EnZaXD 1ca075fe89 Only add minecraft:spit damage type if not sent by the server in 1.20.3->1.20.5 (#4361) 2025-01-27 22:03:12 +01:00
EnZaXD d7c50a0c06 Remove newly added registry entries when already sent be the server (#4352)
Closes https://github.com/ViaVersion/ViaFabricPlus/issues/683
2025-01-26 22:15:48 +01:00
github-actions[bot]andgradle-update-robot 0e98839cee Update Gradle Wrapper from 8.12 to 8.12.1 (#4359)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-01-26 20:01:35 +01:00
EnZaXD 512ceeb401 Rewrite sound event in consumable/equippable components (#4358) 2025-01-25 22:15:55 +01:00
lowercasebtwandEnZaXD 1bf04b4769 Use "intentionally_empty" sound event for 1.8 blocking (#4357)
* Use "intentionally_empty" sound event for 1.8 blocking

* Rather use the sound identifier

---------

Co-authored-by: EnZaXD <florian.michael07@gmail.com>
2025-01-24 22:31:35 +01:00
Nassim Jahnke e24981031b Fix optional explosions hover event deserialization
Fixes ViaVersion/ViaBackwards#952
2025-01-17 12:29:20 +01:00
Nassim Jahnke 261188569d Update custom model data in items in block entities 2025-01-16 13:15:22 +01:00
EnZaXD d2f35708ed Add tag->component handlers in 1.20.5->1.21 component rewriter (#4172)
Used for hover event handling in ViaBackwards
2025-01-15 11:51:44 +01:00
EnZaXD d282f37483 Fix tracking of falling blocks (#4344)
* Fix tracking of falling blocks

Since they use the data int, we have to try get() without taking it in as it will otherwise always fail.

* Prevent server from sending bad data

* Null check
2025-01-11 23:04:22 +01:00
Nassim Jahnke b244776cc9 Move up method to ComponentRewriter interface 2025-01-10 21:25:38 +01:00
Nassim Jahnke 3418e2c21a Prepare ComponentRewriter for 1.21.5 changes 2025-01-10 20:56:36 +01:00
EnZaXD d05bdd9eda Keep empty items in CONTAINER in 1.20.3->1.20.5 (#4338) 2025-01-10 17:43:12 +01:00
EnZaXD a92e75b8cc Properly track minecart object entity types in <= 1.12.2 (#4339) 2025-01-10 17:07:09 +01:00
369 changed files with 13721 additions and 2497 deletions

No files matched your search

+2 -2
View File
@@ -1,6 +1,6 @@
name: Java CI with Gradle
on: [push, pull_request]
on: [push, pull_request, workflow_dispatch]
jobs:
build:
@@ -26,7 +26,7 @@ jobs:
run: ./gradlew build
- name: Upload Artifacts to GitHub
# Only upload on the preview repository as there is no CI job for it.
if: ${{ github.repository == 'ViaVersionDev' && github.ref_name == 'preview' }}
if: ${{ github.repository == 'ViaVersion/ViaVersionDev' && github.ref_name == 'preview' }}
uses: actions/upload-artifact@v4
with:
name: Artifacts
+1
View File
@@ -4,6 +4,7 @@ on:
branches:
- master
- dev
workflow_dispatch:
jobs:
publish:
+1 -1
View File
@@ -18,7 +18,7 @@ Supported Versions:
![Table (https://i.imgur.com/zrQTcf0.png)](https://i.imgur.com/zrQTcf0.png)
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
**User Docs:** https://docs.viaversion.com
Snapshot support
--------
+5 -1
View File
@@ -29,7 +29,11 @@ dependencies {
api(libs.snakeYaml)
compileOnlyApi(libs.netty)
compileOnlyApi(libs.guava)
compileOnlyApi(libs.guava) {
exclude("com.google.errorprone", "error_prone_annotations")
exclude("org.jspecify", "jspecify")
exclude("com.google.j2objc", "j2objc-annotations")
}
compileOnlyApi(libs.checkerQual)
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -114,7 +114,8 @@ public interface ViaAPI<T> {
ProtocolVersion getPlayerProtocolVersion(UUID uuid);
/**
* Returns whether Via injected into this player connection.
* Returns whether Via injected into this player connection. Note that this method may not work on
* clientside implementations and is generally not recommended to be used. Use {@link ConnectionManager} instead.
*
* @param uuid uuid of the player
* @return whether Via has a cached a UserConnection for this player
@@ -122,7 +123,8 @@ public interface ViaAPI<T> {
boolean isInjected(UUID uuid);
/**
* Returns the Via injected UserConnection if present.
* Returns whether Via injected into this player connection. Note that this method may not work on
* clientside implementations and is generally not recommended to be used. Use {@link ConnectionManager} instead.
*
* @param uuid uuid of the player
* @return user connection if present
@@ -66,7 +66,7 @@ public interface ViaSubCommand {
*
* @param sender Command sender
* @param args Arguments
* @return commands executed succesfully if false, show usage
* @return commands executed successfully if false, show usage
*/
boolean execute(ViaCommandSender sender, String[] args);
@@ -30,7 +30,7 @@ public interface ViaVersionCommand {
* Register your own subcommand inside ViaVersion
*
* @param command Your own SubCommand instance to handle it.
* @throws IllegalArgumentException throws an exception when the subcommand already exists or if it's not valid, example: spacee
* @throws IllegalArgumentException throws an exception when the subcommand already exists or if it's not valid, example: space
*/
void registerSubCommand(ViaSubCommand command);
@@ -285,6 +285,13 @@ public interface ViaVersionConfig extends Config {
*/
boolean isSuppressConversionWarnings();
/**
* Should we hide errors that occur when trying to convert text components?
*
* @return true if enabled
*/
boolean isSuppressTextComponentConversionWarnings();
/**
* Should we disable the 1.13 auto-complete feature to stop spam kicks? (for any server lower than 1.13)
*
@@ -28,51 +28,81 @@ import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Handles injected UserConnections
* Handles injected UserConnections.
* Check {@link UserConnection#isServerSide()} and {@link UserConnection#isClientSide()} to determine the connection type.
*/
public interface ConnectionManager {
/**
* Returns if Via injected into this player connection.
* Returns if Via has injected. See above for the connection types.
*
* @param playerId player uuid
* @param uuid player uuid
* @return true if the player is handled by Via
*/
boolean isClientConnected(UUID playerId);
boolean hasServerConnection(UUID uuid);
/**
* Frontend connections will have the UUID stored. Override this if your platform isn't always frontend.
* UUIDs can't be duplicate between frontend connections.
*
* @return true if the user is a frontend connection
*/
default boolean isFrontEnd(UserConnection connection) {
return !connection.isClientSide();
@Deprecated
default boolean isClientConnected(UUID uuid) {
return hasServerConnection(uuid);
}
/**
* Returns the frontend UserConnection from the player connected to this proxy server
* Returns null when there isn't a server or connection was not found
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
* Returns if Via has injected. See above for the connection types.
*
* @return frontend UserConnection of the player connected to this proxy server
* @param uuid player uuid
* @return true if the player is handled by Via
*/
@Nullable UserConnection getConnectedClient(UUID clientIdentifier);
boolean hasClientConnection(UUID uuid);
/**
* Returns the UUID from the frontend connection to this proxy server
* Returns null when there isn't a server or this connection isn't frontend, or it doesn't have an id
* Returns the server UserConnection. See above for the connection types.
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
*
* @return UUID of the frontend connection to this proxy server
* @return server UserConnection of the player or null
*/
@Nullable UUID getConnectedClientId(UserConnection connection);
@Nullable
UserConnection getServerConnection(UUID uuid);
@Deprecated
@Nullable default UserConnection getConnectedClient(UUID uuid) {
return getServerConnection(uuid);
}
/**
* Returns the client UserConnection. See above for the connection types.
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
*
* @return client UserConnection of the player or null
*/
@Nullable
UserConnection getClientConnection(UUID uuid);
/**
* Returns a map containing the UUIDs and server UserConnections
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and frontend UserConnections
*/
Map<UUID, UserConnection> getServerConnections();
@Deprecated
default Map<UUID, UserConnection> getConnectedClients() {
return getServerConnections();
}
/**
* Returns a map containing the UUIDs and client UserConnections
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and client UserConnections
*/
Map<UUID, UserConnection> getClientConnections();
/**
* Returns all UserConnections which are registered
@@ -84,15 +114,6 @@ public interface ConnectionManager {
*/
Set<UserConnection> getConnections();
/**
* Returns a map containing the UUIDs and frontend UserConnections from players connected to this proxy server
* Returns empty list when there isn't a server
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and frontend UserConnections from players connected to this proxy server
*/
Map<UUID, UserConnection> getConnectedClients();
void onLoginSuccess(UserConnection connection);
void onDisconnect(UserConnection connection);
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.connection;
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
@@ -99,6 +100,23 @@ public interface UserConnection {
*/
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
/**
* Adds an item hasher to the user connection.
*
* @param protocolClass protocol class
* @param itemHasher item hasher
*/
void addItemHasher(Class<? extends Protocol> protocolClass, ItemHasher itemHasher);
/**
* Returns the item hasher by the given protocol class if present.
*
* @param protocolClass protocol class
* @param <T> item hasher type
* @return item hasher if present
*/
@Nullable <T extends ItemHasher> T getItemHasher(Class<? extends Protocol> protocolClass);
/**
* Returns the client world by the given protocol class if present.
*
@@ -319,23 +337,35 @@ public interface UserConnection {
void setPendingDisconnect(boolean pendingDisconnect);
/**
* Returns whether this is a client-side connection.
* This is a mod integrated into the client itself, or for example a backend Velocity connection.
* Returns whether this is a backend connection.
* This is a mod integrated into the client, or for example a backend Velocity connection.
*
* @return whether this is a client-side connection
* @return whether this is a backend connection
*/
boolean isClientSide();
/**
* Returns whether this is a frontend connection.
* This is a plugin integrated into the server, or for example a frontend Velocity connection.
*
* @return whether this is a frontend connection
*/
default boolean isServerSide() {
return !isClientSide();
}
/**
* Returns whether {@link ViaVersionConfig#blockedProtocolVersions()} should be checked for this connection.
*
* @return whether blocked protocols should be applied
*/
boolean shouldApplyBlockProtocol();
default boolean shouldApplyBlockProtocol() {
return isServerSide();
}
/**
* Returns a newly generated uuid that will let a packet be passed through without
* transformig its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
* transforming its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
*
* @return generated passthrough token
*/
@@ -123,6 +123,20 @@ public interface EntityTracker {
*/
void setClientEntityId(int clientEntityId);
/**
* Returns whether the client player has the "insta build" ability, usually from creative mode.
*
* @return whether the client player can insta build
*/
boolean canInstaBuild();
/**
* Sets whether the client player has the "insta build" ability, usually from creative mode.
*
* @param instaBuild whether the client player can insta build
*/
void setInstaBuild(boolean instaBuild);
/**
* Returns the current world section height (block height / 16).
* This is always 16 for sub 1.17 worlds.
@@ -0,0 +1,51 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.data.item;
import java.util.List;
/**
* Used for converting items to hashed items and caching them for later use during serverbound packets.
* <p>
* Most of this stays in the internal module given non-permanent, imperfect caching as well as missing converters.
*/
public interface ItemHasher {
/**
* Returns whether this connection is currently processing a clientbound player inventory packet.
* <p>
* Used for checking when it is necessary to track/process item data hashes.
*
* @return true if processing a clientbound inventory packet, false otherwise
*/
boolean isProcessingClientboundInventoryPacket();
void setProcessingClientboundInventoryPacket(boolean processingClientboundInventoryPacket);
/**
* Sets the enchantment registry for this connection.
*
* @param enchantments list of enchantment identifiers
*/
void setEnchantments(List<String> enchantments);
}
@@ -22,7 +22,6 @@
*/
package com.viaversion.viaversion.api.debug;
import com.google.common.annotations.Beta;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
@@ -50,7 +49,6 @@ public interface DebugHandler {
*
* @param packetTypeName packet type name
*/
@Beta
void addPacketTypeNameToLog(String packetTypeName);
/**
@@ -59,7 +57,6 @@ public interface DebugHandler {
*
* @param packetType packet type
*/
@Beta
void addPacketTypeToLog(PacketType packetType);
/**
@@ -67,22 +64,44 @@ public interface DebugHandler {
*
* @param packetTypeName packet type name
*/
@Beta
boolean removePacketTypeNameToLog(String packetTypeName);
/**
* Resets packet type filters.
*/
@Beta
void clearPacketTypesToLog();
/**
* Sets whether packets should be logged before and after being transformed.
*
* @param logPacketTransform whether packets should be logged
*/
default void setLogPacketTransform(boolean logPacketTransform) {
setLogPrePacketTransform(logPacketTransform);
setLogPostPacketTransform(logPacketTransform);
}
/**
* Returns whether packets should be logged before being transformed.
* Set to true by default.
*
* @return whether packets should be logged before being transformed
*/
boolean logPrePacketTransform();
/**
* Sets whether packets should be logged before being transformed.
*
* @param logPrePacketTransform whether packets should be logged before being transformed
*/
void setLogPrePacketTransform(boolean logPrePacketTransform);
/**
* Returns whether packets should be logged after being transformed.
* Set to false by default.
*
* @return whether packets should be logged after being transformed
*/
@Beta
boolean logPostPacketTransform();
/**
@@ -90,7 +109,6 @@ public interface DebugHandler {
*
* @param logPostPacketTransform whether packets should be logged after being transformed
*/
@Beta
void setLogPostPacketTransform(boolean logPostPacketTransform);
/**
@@ -103,7 +121,6 @@ public interface DebugHandler {
*/
boolean shouldLog(PacketWrapper wrapper, Direction direction);
@Beta
default void enableAndLogIds(final PacketType... packetTypes) {
setEnabled(true);
for (final PacketType packetType : packetTypes) {
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents an animal variant (e.g. for cows, pigs, chickens).
*
* @param modelType model type id
* @param texture texture path
* @param biomes biomes this variant can spawn in, if limited to specific biomes
*/
public record AnimalVariant(int modelType, String texture, @Nullable HolderSet biomes) {
public static HolderType<AnimalVariant> TYPE = new HolderType<>() {
@Override
public AnimalVariant readDirect(final ByteBuf buffer) {
final int modelType = Types.VAR_INT.readPrimitive(buffer);
final String texture = Types.STRING.read(buffer);
final HolderSet biomes = Types.OPTIONAL_HOLDER_SET.read(buffer);
return new AnimalVariant(modelType, texture, biomes);
}
@Override
public void writeDirect(final ByteBuf buffer, final AnimalVariant variant) {
Types.VAR_INT.writePrimitive(buffer, variant.modelType());
Types.STRING.write(buffer, variant.texture());
Types.OPTIONAL_HOLDER_SET.write(buffer, variant.biomes());
}
};
}
@@ -58,7 +58,7 @@ public class BlockChangeRecord1_16_2 implements BlockChangeRecord {
@Override
public short getY(int chunkSectionY) {
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: " + chunkSectionY);
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: %s", chunkSectionY);
return (short) ((chunkSectionY << 4) + sectionY);
}
@@ -0,0 +1,82 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
public interface EitherHolder<T> {
/**
* Returns a direct or indirect value holder.
*
* @param value the value
* @param <T> the type of the value
* @return a new direct holder
*/
static <T> EitherHolder<T> of(final Holder<T> value) {
return new EitherHolderImpl<>(value, null);
}
/**
* Returns an indirect holder via the resource key.
*
* @param key the resource key
* @param <T> the type of the value
* @return a new holder with the given resource key
*/
static <T> EitherHolder<T> of(final String key) {
return new EitherHolderImpl<>(null, key);
}
/**
* Returns true if this holder is backed by a direct value.
*
* @return true if the holder is direct
* @see #hasKey()
*/
boolean hasHolder();
/**
* Returns true if this holder has a resource key.
*
* @return true if this holder has a resource key
* @see #hasHolder()
*/
boolean hasKey();
/**
* Returns the value of this holder.
*
* @return the value of this holder
* @throws IllegalArgumentException if this contains a resource key instead of a holder
* @see #hasHolder()
*/
Holder<T> holder();
/**
* Returns the resource key.
*
* @return the resource key
* @throws IllegalArgumentException if this contains a holder instead of a resource key
* @see #hasKey()
*/
String key();
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.util.EitherImpl;
final class EitherHolderImpl<T> extends EitherImpl<Holder<T>, String> implements EitherHolder<T> {
EitherHolderImpl(final Holder<T> left, final String value) {
super(left, value);
}
@Override
public boolean hasHolder() {
return isLeft();
}
@Override
public boolean hasKey() {
return isRight();
}
@Override
public Holder<T> holder() {
Preconditions.checkArgument(hasHolder(), "Either does not have a holder");
return left();
}
@Override
public String key() {
Preconditions.checkArgument(hasKey(), "Either does not have a key");
return right();
}
}
@@ -24,22 +24,28 @@ package com.viaversion.viaversion.api.minecraft;
public enum GameMode {
NOT_SET(""),
SURVIVAL("Survival Mode"),
CREATIVE("Creative Mode"),
ADVENTURE("Adventure Mode"),
SPECTATOR("Spectator Mode");
NOT_SET("", -1),
SURVIVAL("Survival Mode", 0),
CREATIVE("Creative Mode", 1),
ADVENTURE("Adventure Mode", 2),
SPECTATOR("Spectator Mode", 3);
private final String text;
private final int id;
GameMode(String text) {
GameMode(String text, final int id) {
this.text = text;
this.id = id;
}
public String text() {
return text;
}
public int id() {
return id;
}
public static GameMode getById(int id) {
return switch (id) {
case -1 -> NOT_SET;
@@ -22,11 +22,31 @@
*/
package com.viaversion.viaversion.api.minecraft;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
public record GameProfile(@Nullable String name, @Nullable UUID id, Property[] properties) {
public GameProfile(@Nullable final String name, @Nullable final UUID id) {
this(name, id, new Property[0]);
}
public Map<String, List<Property>> propertiesMap() {
final Map<String, List<Property>> map = new HashMap<>();
for (Property property : properties) {
map.computeIfAbsent(property.name(), k -> new ArrayList<>()).add(property);
}
return map;
}
public record Property(String name, String value, @Nullable String signature) {
public Property(final String name, final String value) {
this(name, value, null);
}
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
public interface Holder<T> {
@@ -89,4 +90,12 @@ public interface Holder<T> {
* @return a new holder with the id rewritten, or self
*/
Holder<T> updateId(final Int2IntFunction rewriteFunction);
/**
* Returns a new holder with the value rewritten using the given function, or self if this is an id holder or the value did not change.
*
* @param rewriteFunction the function to rewrite the value
* @return a new holder with the value rewritten, or self
*/
Holder<T> updateValue(final Function<T, T> rewriteFunction);
}
@@ -67,11 +67,17 @@ final class HolderSetImpl {
@Override
public HolderSet rewrite(final Int2IntFunction idRewriter) {
// Filter out negative ids as they would come from missing VB mapping data. This happens especially
// with block ids which are not mapped and thus written as -1 so VV rewriters can cancel them nicely.
final int[] mappedIds = new int[ids.length];
for (int i = 0; i < mappedIds.length; i++) {
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
int validCount = 0;
for (final int id : ids) {
final int mappedId = idRewriter.applyAsInt(id);
if (mappedId != -1) {
mappedIds[validCount++] = mappedId;
}
}
return new Ids(mappedIds);
return new Ids(validCount == ids.length ? mappedIds : Arrays.copyOf(mappedIds, validCount));
}
@Override
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
record IdHolder<T>(int id) implements Holder<T> {
@@ -57,4 +58,9 @@ record IdHolder<T>(int id) implements Holder<T> {
}
return Holder.of(rewrittenId);
}
@Override
public Holder<T> updateValue(final Function<T, T> rewriteFunction) {
return this;
}
}
@@ -22,15 +22,15 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.IdHolder;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class Particle implements IdHolder {
public final class Particle implements IdHolder, Copyable {
private final List<ParticleData<?>> arguments = new ArrayList<>(4);
private int id;
@@ -73,6 +73,7 @@ public final class Particle implements IdHolder {
arguments.set(index, new ParticleData<>(type, value));
}
@Override
public Particle copy() {
final Particle particle = new Particle(id);
for (ParticleData<?> argument : arguments) {
@@ -89,7 +90,7 @@ public final class Particle implements IdHolder {
'}';
}
public static final class ParticleData<T> {
public static final class ParticleData<T> implements Copyable {
private final Type<T> type;
private T value;
@@ -118,12 +119,9 @@ public final class Particle implements IdHolder {
wrapper.write(type, value);
}
@Override
public ParticleData<T> copy() {
if (value instanceof Item item) {
return new ParticleData<>(type, (T) item.copy());
} else {
return new ParticleData<>(type, value);
}
return new ParticleData<>(type, Copyable.copy(value));
}
@Override
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.Copyable;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@@ -31,12 +32,13 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* @param key key of the registry entry
* @param tag data of the registry entry, or null if the client should use its default
*/
public record RegistryEntry(String key, @Nullable Tag tag) {
public record RegistryEntry(String key, @Nullable Tag tag) implements Copyable {
public RegistryEntry withKey(final String key) {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
@Override
public RegistryEntry copy() {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
record ValueHolder<T>(T value) implements Holder<T> {
@@ -45,4 +46,10 @@ record ValueHolder<T>(T value) implements Holder<T> {
public Holder<T> updateId(final Int2IntFunction rewriteFunction) {
return this;
}
@Override
public Holder<T> updateValue(final Function<T, T> rewriteFunction) {
final T rewrittenValue = rewriteFunction.apply(value);
return rewrittenValue != value ? Holder.of(rewrittenValue) : this;
}
}
@@ -143,6 +143,16 @@ public class BaseChunk implements Chunk {
this.heightMap = heightMap;
}
@Override
public Heightmap[] heightmaps() {
throw new UnsupportedOperationException();
}
@Override
public void setHeightmaps(final Heightmap[] heightmaps) {
throw new UnsupportedOperationException();
}
@Override
public List<CompoundTag> getBlockEntities() {
return blockEntities;
@@ -79,7 +79,8 @@ public interface Chunk {
* @return chunk section bit mask, only non-null for 1.17+ chunks
* @see #getBitmask()
*/
@Nullable BitSet getChunkMask();
@Nullable
BitSet getChunkMask();
void setChunkMask(BitSet chunkSectionMask);
@@ -88,7 +89,8 @@ public interface Chunk {
*
* @return array of nullable chunk sections
*/
@Nullable ChunkSection[] getSections();
@Nullable
ChunkSection[] getSections();
void setSections(ChunkSection[] sections);
@@ -106,10 +108,15 @@ public interface Chunk {
*
* @return compoundtag containing heightmaps if present
*/
@Nullable CompoundTag getHeightMap();
@Nullable
CompoundTag getHeightMap();
void setHeightMap(@Nullable CompoundTag heightMap);
Heightmap[] heightmaps();
void setHeightmaps(Heightmap[] heightmaps);
/**
* Returns a list of block entities.
*
@@ -123,6 +123,16 @@ public class Chunk1_18 implements Chunk {
this.heightMap = heightMap;
}
@Override
public Heightmap[] heightmaps() {
throw new UnsupportedOperationException();
}
@Override
public void setHeightmaps(final Heightmap[] heightmaps) {
throw new UnsupportedOperationException();
}
@Override
public List<CompoundTag> getBlockEntities() {
throw new UnsupportedOperationException();
@@ -0,0 +1,145 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import java.util.BitSet;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public class Chunk1_21_5 implements Chunk {
protected final int x;
protected final int z;
protected ChunkSection[] sections;
protected Heightmap[] heightmaps;
protected final List<BlockEntity> blockEntities;
public Chunk1_21_5(int x, int z, ChunkSection[] sections, Heightmap[] heightmaps, List<BlockEntity> blockEntities) {
this.x = x;
this.z = z;
this.sections = sections;
this.heightmaps = heightmaps;
this.blockEntities = blockEntities;
}
@Override
public boolean isBiomeData() {
return false;
}
@Override
public int getX() {
return x;
}
@Override
public int getZ() {
return z;
}
@Override
public boolean isFullChunk() {
return true;
}
@Override
public boolean isIgnoreOldLightData() {
return false;
}
@Override
public void setIgnoreOldLightData(boolean ignoreOldLightData) {
throw new UnsupportedOperationException();
}
@Override
public int getBitmask() {
return -1;
}
@Override
public void setBitmask(int bitmask) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable BitSet getChunkMask() {
return null;
}
@Override
public void setChunkMask(BitSet chunkSectionMask) {
throw new UnsupportedOperationException();
}
@Override
public ChunkSection[] getSections() {
return sections;
}
@Override
public void setSections(ChunkSection[] sections) {
this.sections = sections;
}
@Override
public int @Nullable [] getBiomeData() {
return null;
}
@Override
public void setBiomeData(int @Nullable [] biomeData) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable CompoundTag getHeightMap() {
throw new UnsupportedOperationException();
}
@Override
public void setHeightMap(final CompoundTag heightMap) {
throw new UnsupportedOperationException();
}
@Override
public Heightmap[] heightmaps() {
return heightmaps;
}
@Override
public void setHeightmaps(final Heightmap[] heightmaps) {
this.heightmaps = heightmaps;
}
@Override
public List<CompoundTag> getBlockEntities() {
throw new UnsupportedOperationException();
}
@Override
public List<BlockEntity> blockEntities() {
return blockEntities;
}
}
@@ -0,0 +1,26 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
public record Heightmap(int type, long[] data) {
}
@@ -0,0 +1,54 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.codec;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.util.Key;
import java.util.List;
public interface CodecContext {
RegistryAccess registryAccess();
boolean mapped();
boolean isSupported(StructuredDataKey<?> key);
interface RegistryAccess {
Key item(int id);
Key enchantment(int id);
Key attributeModifier(int id);
Key dataComponentType(int id);
static RegistryAccess of(final List<String> enchantments, final MappingData mappingData) {
return new RegistryAccessImpl(enchantments, mappingData);
}
RegistryAccess withMapped(boolean mapped);
}
}
@@ -0,0 +1,133 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.codec;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import java.util.Objects;
import java.util.function.Consumer;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface Ops {
CodecContext context();
void writeByte(byte b);
void writeBytes(byte[] array);
void writeBoolean(boolean b);
void writeShort(short s);
void writeString(CharSequence sequence);
void writeInt(int i);
void writeLong(long l);
void writeFloat(float f);
void writeDouble(double d);
void writeInts(int[] array);
void writeLongs(long[] array);
void writeList(Consumer<ListSerializer> consumer);
void writeMap(Consumer<MapSerializer> consumer);
<V> void write(final Type<V> type, final V value);
interface ListSerializer {
<V> ListSerializer write(Type<V> valueType, V value);
ListSerializer writeList(Consumer<ListSerializer> consumer);
ListSerializer writeMap(Consumer<MapSerializer> consumer);
}
interface MapSerializer {
<K, V> MapSerializer write(Type<K> keyType, K key, Type<V> valueType, V value);
default <V> MapSerializer write(final String key, final Type<V> type, final V value) {
write(Types.STRING, key, type, value);
return this;
}
/**
* Writes the given value or default value if the value is null.
*
* @param key map key
* @param type type of the value
* @param value the value to write, or null
* @param def default value to write if the value is null
* @return self
* @param <V> value type
*/
default <V> MapSerializer write(final String key, final Type<V> type, @Nullable final V value, final V def) {
write(Types.STRING, key, type, value != null ? value : def);
return this;
}
/**
* Writes the given value if it is not null.
*
* @param key map key
* @param type type of the value
* @param value the value to write, or null
* @return self
* @param <V> value type
*/
default <V> MapSerializer writeOptional(final String key, final Type<V> type, @Nullable final V value) {
if (value != null) {
write(Types.STRING, key, type, value);
}
return this;
}
/**
* Writes the given value if it is not null and not equal to the default value.
*
* @param key map key
* @param type type of the value
* @param value the value to write, or null
* @param def default value to compare against
* @return self
* @param <V> value type
*/
default <V> MapSerializer writeOptional(final String key, final Type<V> type, @Nullable final V value, final V def) {
if (value != null && !Objects.deepEquals(value, def)) {
write(Types.STRING, key, type, value);
}
return this;
}
MapSerializer writeList(String key, Consumer<ListSerializer> consumer);
MapSerializer writeMap(String key, Consumer<MapSerializer> consumer);
}
}
@@ -0,0 +1,82 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.codec;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.util.Key;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
final class RegistryAccessImpl implements CodecContext.RegistryAccess {
private final List<String> enchantments;
private final MappingData mappingData;
private final boolean mapped;
RegistryAccessImpl(final List<String> enchantments, final MappingData mappingData) {
this.enchantments = enchantments;
this.mappingData = mappingData;
this.mapped = false;
}
private RegistryAccessImpl(final List<String> enchantments, final MappingData mappingData, final boolean mapped) {
this.enchantments = enchantments;
this.mappingData = mappingData;
this.mapped = mapped;
}
@Override
public Key item(final int id) {
return key(mappingData.getFullItemMappings(), id);
}
@Override
public Key enchantment(final int id) {
final String identifier = id >= 0 && id < this.enchantments.size() ? this.enchantments.get(id) : null;
return key(identifier, id);
}
@Override
public Key attributeModifier(final int id) {
return key(mappingData.getAttributeMappings(), id);
}
@Override
public Key dataComponentType(final int id) {
return key(mappingData.getDataComponentSerializerMappings(), id);
}
private Key key(final FullMappings mappings, final int id) {
final String identifier = mapped ? mappings.mappedIdentifier(id) : mappings.identifier(id);
return key(identifier, id);
}
private Key key(@Nullable final String identifier, final int id) {
return identifier != null ? Key.of(identifier) : Key.of("viaversion", "unknown/" + id);
}
@Override
public CodecContext.RegistryAccess withMapped(final boolean mapped) {
return this.mapped == mapped ? this : new RegistryAccessImpl(this.enchantments, this.mappingData, mapped);
}
}
@@ -0,0 +1,45 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.codec.hash;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
/**
* Hash operations. Note that this is different from Vanilla codecs, where this
* instead acts as a (re-usable) hasher directly rather than each method having
* self-contained return values.
*/
public interface Hasher extends Ops {
/**
* Returns the current hash value.
*
* @return the current hash value
*/
int hash();
/**
* Resets the hasher to its initial state.
*/
void reset();
}
@@ -53,6 +53,11 @@ final class EmptyStructuredData<T> implements StructuredData<T> {
return this.key;
}
@Override
public StructuredData<T> copy() {
return new EmptyStructuredData<>(this.key, this.id);
}
@Override
public T value() {
return null;
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft.data;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import java.util.Objects;
@@ -59,6 +60,11 @@ final class FilledStructuredData<T> implements StructuredData<T> {
return key;
}
@Override
public StructuredData<T> copy() {
return new FilledStructuredData<>(this.key, Copyable.copy(this.value), this.id);
}
@Override
public T value() {
return value;
@@ -22,11 +22,12 @@
*/
package com.viaversion.viaversion.api.minecraft.data;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.IdHolder;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface StructuredData<T> extends IdHolder {
public interface StructuredData<T> extends IdHolder, Copyable {
/**
* Returns filled structured data, equivalent to an Optional with a value in vanilla.
@@ -52,7 +53,8 @@ public interface StructuredData<T> extends IdHolder {
return new EmptyStructuredData<>(key, id);
}
@Nullable T value();
@Nullable
T value();
void setValue(final T value);
@@ -60,6 +62,9 @@ public interface StructuredData<T> extends IdHolder {
StructuredDataKey<T> key();
@Override
StructuredData<T> copy();
/**
* Returns whether the structured data is present. Even if true, the value may be null.
*
@@ -26,9 +26,11 @@ import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Unit;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -53,7 +55,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* </ul>
* Other methods (e.g. {@link #getData(StructuredDataKey)} and {@link #has(StructuredDataKey)}) will handle both empty and non-empty data.
*/
public final class StructuredDataContainer {
public final class StructuredDataContainer implements Copyable {
private final Map<StructuredDataKey<?>, StructuredData<?>> data;
private FullMappings lookup;
@@ -71,7 +73,7 @@ public final class StructuredDataContainer {
}
public StructuredDataContainer() {
this(new Reference2ObjectOpenHashMap<>());
this(new Reference2ObjectOpenHashMap<>(0));
}
/**
@@ -188,6 +190,20 @@ public final class StructuredDataContainer {
this.data.remove(key);
}
/**
* Removes data by the given keys.
*
* @param keys data keys
* @see #replace(StructuredDataKey, Function)
* @see #replace(StructuredDataKey, StructuredDataKey, Function)
* @see #replaceKey(StructuredDataKey, StructuredDataKey)
*/
public void remove(final Collection<StructuredDataKey<?>> keys) {
for (final StructuredDataKey<?> key : keys) {
this.data.remove(key);
}
}
/**
* Returns whether there is data for the given key, either empty or non-empty.
*
@@ -245,8 +261,13 @@ public final class StructuredDataContainer {
}
}
@Override
public StructuredDataContainer copy() {
final StructuredDataContainer copy = new StructuredDataContainer(new Reference2ObjectOpenHashMap<>(data));
final Reference2ObjectOpenHashMap<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>();
for (final StructuredData<?> value : data.values()) {
map.put(value.key(), value.copy());
}
final StructuredDataContainer copy = new StructuredDataContainer(map);
copy.lookup = this.lookup;
return copy;
}
@@ -263,6 +284,10 @@ public final class StructuredDataContainer {
return data;
}
public boolean isEmpty() {
return data.isEmpty();
}
@Override
public String toString() {
return "StructuredDataContainer{" +
@@ -24,10 +24,15 @@ package com.viaversion.viaversion.api.minecraft.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.GameProfile;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_20_5;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_2;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_5;
import com.viaversion.viaversion.api.minecraft.item.data.AdventureModePredicate;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrim;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
@@ -35,14 +40,16 @@ import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
import com.viaversion.viaversion.api.minecraft.item.data.BlocksAttacks;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant;
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantable;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.data.EnumTypes;
import com.viaversion.viaversion.api.minecraft.item.data.Equippable;
import com.viaversion.viaversion.api.minecraft.item.data.FilterableString;
import com.viaversion.viaversion.api.minecraft.item.data.FireworkExplosion;
import com.viaversion.viaversion.api.minecraft.item.data.Fireworks;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_20_5;
@@ -53,41 +60,60 @@ import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
import com.viaversion.viaversion.api.minecraft.item.data.TooltipDisplay;
import com.viaversion.viaversion.api.minecraft.item.data.TropicalFishPattern;
import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable;
import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
import com.viaversion.viaversion.api.minecraft.item.data.Weapon;
import com.viaversion.viaversion.api.minecraft.item.data.WritableBook;
import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
import com.viaversion.viaversion.api.type.types.EitherType;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.util.Either;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Unit;
/**
* Holds data component keys.
*
* @param identifier string identifier
* @param type data type
* @param <T> data type
* @see VersionedTypes
*/
public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<CompoundTag> CUSTOM_DATA = new StructuredDataKey<>("custom_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<Integer> MAX_STACK_SIZE = new StructuredDataKey<>("max_stack_size", Types.VAR_INT);
public static final StructuredDataKey<Integer> MAX_DAMAGE = new StructuredDataKey<>("max_damage", Types.VAR_INT);
public static final StructuredDataKey<Integer> DAMAGE = new StructuredDataKey<>("damage", Types.VAR_INT);
public static final StructuredDataKey<Unbreakable> UNBREAKABLE = new StructuredDataKey<>("unbreakable", Unbreakable.TYPE);
public static final StructuredDataKey<Unbreakable> UNBREAKABLE1_20_5 = new StructuredDataKey<>("unbreakable", Unbreakable.TYPE);
public static final StructuredDataKey<Unit> UNBREAKABLE1_21_5 = new StructuredDataKey<>("unbreakable", Types.EMPTY);
public static final StructuredDataKey<Tag> CUSTOM_NAME = new StructuredDataKey<>("custom_name", Types.TAG);
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TAG);
public static final StructuredDataKey<String> ITEM_MODEL = new StructuredDataKey<>("item_model", Types.STRING);
public static final StructuredDataKey<Key> ITEM_MODEL = new StructuredDataKey<>("item_model", Types.RESOURCE_LOCATION);
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", new ArrayType<>(Types.TAG, 256));
public static final StructuredDataKey<Integer> RARITY = new StructuredDataKey<>("rarity", Types.VAR_INT);
public static final StructuredDataKey<Enchantments> ENCHANTMENTS = new StructuredDataKey<>("enchantments", Enchantments.TYPE);
public static final StructuredDataKey<AdventureModePredicate> CAN_PLACE_ON = new StructuredDataKey<>("can_place_on", AdventureModePredicate.TYPE);
public static final StructuredDataKey<AdventureModePredicate> CAN_BREAK = new StructuredDataKey<>("can_break", AdventureModePredicate.TYPE);
public static final StructuredDataKey<Integer> RARITY = new StructuredDataKey<>("rarity", EnumTypes.RARITY);
public static final StructuredDataKey<Enchantments> ENCHANTMENTS1_20_5 = new StructuredDataKey<>("enchantments", Enchantments.TYPE1_20_5);
public static final StructuredDataKey<Enchantments> ENCHANTMENTS1_21_5 = new StructuredDataKey<>("enchantments", Enchantments.TYPE1_21_5);
// 1.21.5+ predicates are in their own key classes
public static final StructuredDataKey<AdventureModePredicate> CAN_PLACE_ON1_20_5 = new StructuredDataKey<>("can_place_on", AdventureModePredicate.TYPE1_20_5);
public static final StructuredDataKey<AdventureModePredicate> CAN_BREAK1_20_5 = new StructuredDataKey<>("can_break", AdventureModePredicate.TYPE1_20_5);
public static final StructuredDataKey<AttributeModifiers1_20_5> ATTRIBUTE_MODIFIERS1_20_5 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_20_5.TYPE);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE1_21);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21_5 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE1_21_5);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21_6 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE1_21_6);
public static final StructuredDataKey<Integer> CUSTOM_MODEL_DATA1_20_5 = new StructuredDataKey<>("custom_model_data", Types.VAR_INT);
public static final StructuredDataKey<CustomModelData1_21_4> CUSTOM_MODEL_DATA1_21_4 = new StructuredDataKey<>("custom_model_data", CustomModelData1_21_4.TYPE);
public static final StructuredDataKey<Unit> HIDE_ADDITIONAL_TOOLTIP = new StructuredDataKey<>("hide_additional_tooltip", Types.EMPTY);
public static final StructuredDataKey<Unit> HIDE_TOOLTIP = new StructuredDataKey<>("hide_tooltip", Types.EMPTY);
public static final StructuredDataKey<TooltipDisplay> TOOLTIP_DISPLAY = new StructuredDataKey<>("tooltip_display", TooltipDisplay.TYPE);
public static final StructuredDataKey<Integer> REPAIR_COST = new StructuredDataKey<>("repair_cost", Types.VAR_INT);
public static final StructuredDataKey<Unit> CREATIVE_SLOT_LOCK = new StructuredDataKey<>("creative_slot_lock", Types.EMPTY);
public static final StructuredDataKey<Boolean> ENCHANTMENT_GLINT_OVERRIDE = new StructuredDataKey<>("enchantment_glint_override", Types.BOOLEAN);
@@ -96,65 +122,98 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_21);
public static final StructuredDataKey<FoodProperties1_21_2> FOOD1_21_2 = new StructuredDataKey<>("food", FoodProperties1_21_2.TYPE);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
public static final StructuredDataKey<Item> USE_REMAINDER1_21_2 = new StructuredDataKey<>("use_remainder", Types1_21_2.ITEM);
public static final StructuredDataKey<Item> USE_REMAINDER1_21_4 = new StructuredDataKey<>("use_remainder", Types1_21_4.ITEM);
public static final StructuredDataKey<UseCooldown> USE_COOLDOWN = new StructuredDataKey<>("use_cooldown", UseCooldown.TYPE);
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
public static final StructuredDataKey<DamageResistant> DAMAGE_RESISTANT = new StructuredDataKey<>("damage_resistant", DamageResistant.TYPE);
public static final StructuredDataKey<ToolProperties> TOOL = new StructuredDataKey<>("tool", ToolProperties.TYPE);
public static final StructuredDataKey<Integer> ENCHANTABLE = new StructuredDataKey<>("enchantable", Types.VAR_INT);
public static final StructuredDataKey<Equippable> EQUIPPABLE = new StructuredDataKey<>("equippable", Equippable.TYPE);
public static final StructuredDataKey<ToolProperties> TOOL1_20_5 = new StructuredDataKey<>("tool", ToolProperties.TYPE1_20_5);
public static final StructuredDataKey<ToolProperties> TOOL1_21_5 = new StructuredDataKey<>("tool", ToolProperties.TYPE1_21_5);
public static final StructuredDataKey<Weapon> WEAPON = new StructuredDataKey<>("weapon", Weapon.TYPE);
public static final StructuredDataKey<Enchantable> ENCHANTABLE = new StructuredDataKey<>("enchantable", Enchantable.TYPE);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_2 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_2);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_5 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_5);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_6 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_6);
public static final StructuredDataKey<HolderSet> REPAIRABLE = new StructuredDataKey<>("repairable", Types.HOLDER_SET);
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
public static final StructuredDataKey<String> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.STRING);
public static final StructuredDataKey<Key> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.RESOURCE_LOCATION);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE);
public static final StructuredDataKey<DyedColor> DYED_COLOR = new StructuredDataKey<>("dyed_color", DyedColor.TYPE);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS1_20_5 = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE1_20_5);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS1_21_5 = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE1_21_5);
public static final StructuredDataKey<DyedColor> DYED_COLOR1_20_5 = new StructuredDataKey<>("dyed_color", DyedColor.TYPE1_20_5);
public static final StructuredDataKey<DyedColor> DYED_COLOR1_21_5 = new StructuredDataKey<>("dyed_color", DyedColor.TYPE1_21_5);
public static final StructuredDataKey<Integer> MAP_COLOR = new StructuredDataKey<>("map_color", Types.INT);
public static final StructuredDataKey<Integer> MAP_ID = new StructuredDataKey<>("map_id", Types.VAR_INT);
public static final StructuredDataKey<CompoundTag> MAP_DECORATIONS = new StructuredDataKey<>("map_decorations", Types.COMPOUND_TAG);
public static final StructuredDataKey<Integer> MAP_POST_PROCESSING = new StructuredDataKey<>("map_post_processing", Types.VAR_INT);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_20_5 = new StructuredDataKey<>("charged_projectiles", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21 = new StructuredDataKey<>("charged_projectiles", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_2 = new StructuredDataKey<>("charged_projectiles", Types1_21_2.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_4 = new StructuredDataKey<>("charged_projectiles", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_20_5 = new StructuredDataKey<>("bundle_contents", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21 = new StructuredDataKey<>("bundle_contents", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_2 = new StructuredDataKey<>("bundle_contents", Types1_21_2.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_4 = new StructuredDataKey<>("bundle_contents", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_20_5 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_20_5);
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_21_2 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_21_2);
public static final StructuredDataKey<Float> POTION_DURATION_SCALE = new StructuredDataKey<>("potion_duration_scale", Types.FLOAT);
public static final StructuredDataKey<SuspiciousStewEffect[]> SUSPICIOUS_STEW_EFFECTS = new StructuredDataKey<>("suspicious_stew_effects", SuspiciousStewEffect.ARRAY_TYPE);
public static final StructuredDataKey<FilterableString[]> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", FilterableString.ARRAY_TYPE);
public static final StructuredDataKey<WritableBook> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", WritableBook.TYPE);
public static final StructuredDataKey<WrittenBook> WRITTEN_BOOK_CONTENT = new StructuredDataKey<>("written_book_content", WrittenBook.TYPE);
public static final StructuredDataKey<ArmorTrim> TRIM1_20_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_20_5);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_2 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_2);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_4 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_4);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_5);
public static final StructuredDataKey<CompoundTag> DEBUG_STICK_STATE = new StructuredDataKey<>("debug_stick_state", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> ENTITY_DATA = new StructuredDataKey<>("entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> BUCKET_ENTITY_DATA = new StructuredDataKey<>("bucket_entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> BLOCK_ENTITY_DATA = new StructuredDataKey<>("block_entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<Holder<Instrument1_20_5>> INSTRUMENT1_20_5 = new StructuredDataKey<>("instrument", Instrument1_20_5.TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT1_21_2 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
public static final StructuredDataKey<EitherHolder<Instrument1_21_2>> INSTRUMENT1_21_5 = new StructuredDataKey<>("instrument", Instrument1_21_2.EITHER_HOLDER_TYPE);
public static final StructuredDataKey<ProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial.TYPE);
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21_5 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21_5);
public static final StructuredDataKey<Key> PROVIDES_BANNER_PATTERNS = new StructuredDataKey<>("provides_banner_patterns", Types.TAG_KEY);
public static final StructuredDataKey<Tag> RECIPES = new StructuredDataKey<>("recipes", Types.TAG);
public static final StructuredDataKey<LodestoneTracker> LODESTONE_TRACKER = new StructuredDataKey<>("lodestone_tracker", LodestoneTracker.TYPE);
public static final StructuredDataKey<FireworkExplosion> FIREWORK_EXPLOSION = new StructuredDataKey<>("firework_explosion", FireworkExplosion.TYPE);
public static final StructuredDataKey<Fireworks> FIREWORKS = new StructuredDataKey<>("fireworks", Fireworks.TYPE);
public static final StructuredDataKey<GameProfile> PROFILE = new StructuredDataKey<>("profile", Types.GAME_PROFILE);
public static final StructuredDataKey<String> NOTE_BLOCK_SOUND = new StructuredDataKey<>("note_block_sound", Types.STRING);
public static final StructuredDataKey<Key> NOTE_BLOCK_SOUND = new StructuredDataKey<>("note_block_sound", Types.RESOURCE_LOCATION);
public static final StructuredDataKey<BannerPatternLayer[]> BANNER_PATTERNS = new StructuredDataKey<>("banner_patterns", BannerPatternLayer.ARRAY_TYPE);
public static final StructuredDataKey<Integer> BASE_COLOR = new StructuredDataKey<>("base_color", Types.VAR_INT);
public static final StructuredDataKey<Integer> BASE_COLOR = new StructuredDataKey<>("base_color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
public static final StructuredDataKey<Item[]> CONTAINER1_20_5 = new StructuredDataKey<>("container", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_21 = new StructuredDataKey<>("container", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_21_2 = new StructuredDataKey<>("container", new ArrayType<>(Types1_21_2.ITEM, 256));
public static final StructuredDataKey<Item[]> CONTAINER1_21_4 = new StructuredDataKey<>("container", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<BlockStateProperties> BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE);
public static final StructuredDataKey<Bee[]> BEES = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE);
public static final StructuredDataKey<Tag> LOCK = new StructuredDataKey<>("lock", Types.TAG);
public static final StructuredDataKey<CompoundTag> CONTAINER_LOOT = new StructuredDataKey<>("container_loot", Types.COMPOUND_TAG);
public static final StructuredDataKey<Holder<SoundEvent>> BREAK_SOUND = new StructuredDataKey<>("break_sound", Types.SOUND_EVENT);
public static final StructuredDataKey<Integer> VILLAGER_VARIANT = new StructuredDataKey<>("villager/variant", EnumTypes.VILLAGER_TYPE);
public static final StructuredDataKey<Integer> WOLF_VARIANT = new StructuredDataKey<>("wolf/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> WOLF_SOUND_VARIANT = new StructuredDataKey<>("wolf/sound_variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> WOLF_COLLAR = new StructuredDataKey<>("wolf/collar", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> FOX_VARIANT = new StructuredDataKey<>("fox/variant", EnumTypes.FOX_VARIANT);
public static final StructuredDataKey<Integer> SALMON_SIZE = new StructuredDataKey<>("salmon/size", EnumTypes.SALMON_VARIANT);
public static final StructuredDataKey<Integer> PARROT_VARIANT = new StructuredDataKey<>("parrot/variant", EnumTypes.PARROT_VARIANT);
public static final StructuredDataKey<TropicalFishPattern> TROPICAL_FISH_PATTERN = new StructuredDataKey<>("tropical_fish/pattern", TropicalFishPattern.TYPE);
public static final StructuredDataKey<Integer> TROPICAL_FISH_BASE_COLOR = new StructuredDataKey<>("tropical_fish/base_color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> TROPICAL_FISH_PATTERN_COLOR = new StructuredDataKey<>("tropical_fish/pattern_color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> MOOSHROOM_VARIANT = new StructuredDataKey<>("mooshroom/variant", EnumTypes.MUSHROOM_COW_VARIANT);
public static final StructuredDataKey<Integer> RABBIT_VARIANT = new StructuredDataKey<>("rabbit/variant", EnumTypes.RABBIT_VARIANT);
public static final StructuredDataKey<Integer> PIG_VARIANT = new StructuredDataKey<>("pig/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> COW_VARIANT = new StructuredDataKey<>("cow/variant", Types.VAR_INT);
public static final StructuredDataKey<Either<Integer, String>> CHICKEN_VARIANT = new StructuredDataKey<>("chicken/variant", new EitherType<>(Types.VAR_INT, Types.STRING)); // ???
public static final StructuredDataKey<Integer> FROG_VARIANT = new StructuredDataKey<>("frog/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> HORSE_VARIANT = new StructuredDataKey<>("horse/variant", EnumTypes.HORSE_VARIANT);
public static final StructuredDataKey<Holder<PaintingVariant>> PAINTING_VARIANT = new StructuredDataKey<>("painting/variant", PaintingVariant.TYPE1_21_2);
public static final StructuredDataKey<Integer> LLAMA_VARIANT = new StructuredDataKey<>("llama/variant", EnumTypes.LLAMA_VARIANT);
public static final StructuredDataKey<Integer> AXOLOTL_VARIANT = new StructuredDataKey<>("axolotl/variant", EnumTypes.AXOLOTL_VARIANT);
public static final StructuredDataKey<Integer> CAT_VARIANT = new StructuredDataKey<>("cat/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> CAT_COLLAR = new StructuredDataKey<>("cat/collar", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> SHEEP_COLOR = new StructuredDataKey<>("sheep/color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> SHULKER_COLOR = new StructuredDataKey<>("shulker/color", EnumTypes.DYE_COLOR);
// These are only safe to use after protocol loading
public static final StructuredDataKeys1_20_5 V1_20_5 = VersionedTypes.V1_20_5.structuredDataKeys();
public static final StructuredDataKeys1_20_5 V1_21 = VersionedTypes.V1_21.structuredDataKeys();
public static final StructuredDataKeys1_21_2 V1_21_2 = VersionedTypes.V1_21_2.structuredDataKeys();
public static final StructuredDataKeys1_21_2 V1_21_4 = VersionedTypes.V1_21_4.structuredDataKeys();
public static final StructuredDataKeys1_21_5 V1_21_5 = VersionedTypes.V1_21_5.structuredDataKeys();
public static final StructuredDataKeys1_21_5 V1_21_6 = VersionedTypes.V1_21_6.structuredDataKeys();
@Override
public String toString() {
@@ -0,0 +1,52 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.predicate;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public record DataComponentMatchers(StructuredData<?>[] exactPredicates, DataComponentPredicate[] predicates) {
public static final class DataComponentMatchersType extends Type<DataComponentMatchers> {
private final Type<StructuredData<?>[]> dataArrayType;
public DataComponentMatchersType(final Type<StructuredData<?>[]> dataArrayType) {
super(DataComponentMatchers.class);
this.dataArrayType = dataArrayType;
}
@Override
public DataComponentMatchers read(final ByteBuf buffer) {
final StructuredData<?>[] exactPredicates = dataArrayType.read(buffer);
final DataComponentPredicate[] partialPredicates = DataComponentPredicate.ARRAY_TYPE.read(buffer);
return new DataComponentMatchers(exactPredicates, partialPredicates);
}
@Override
public void write(final ByteBuf buffer, final DataComponentMatchers value) {
dataArrayType.write(buffer, value.exactPredicates());
DataComponentPredicate.ARRAY_TYPE.write(buffer, value.predicates());
}
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.predicate;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
public record DataComponentPredicate(int id, Tag predicate) {
public static final Type<DataComponentPredicate> TYPE = new Type<>(DataComponentPredicate.class) {
@Override
public DataComponentPredicate read(final ByteBuf buffer) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final Tag predicate = Types.TAG.read(buffer);
return new DataComponentPredicate(id, predicate);
}
@Override
public void write(final ByteBuf buffer, final DataComponentPredicate value) {
Types.VAR_INT.writePrimitive(buffer, value.id());
Types.TAG.write(buffer, value.predicate());
}
};
public static final Type<DataComponentPredicate[]> ARRAY_TYPE = new ArrayType<>(TYPE, 64);
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys1_20_5 extends VersionedStructuredDataKeys {
public final StructuredDataKey<Item[]> container;
public final StructuredDataKey<Item[]> chargedProjectiles;
public final StructuredDataKey<Item[]> bundleContents;
public StructuredDataKeys1_20_5(final VersionedTypesHolder types) {
this.container = add("container", types.itemArray());
this.chargedProjectiles = add("charged_projectiles", types.itemArray());
this.bundleContents = add("bundle_contents", types.itemArray());
}
}
@@ -0,0 +1,43 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.ContainterContents.ContainerContentsType;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys1_21_2 extends VersionedStructuredDataKeys {
public final StructuredDataKey<Item[]> container;
public final StructuredDataKey<Item[]> chargedProjectiles;
public final StructuredDataKey<Item[]> bundleContents;
public final StructuredDataKey<Item> useRemainder;
public StructuredDataKeys1_21_2(final VersionedTypesHolder types) {
this.container = add("container", new ContainerContentsType(types.item()));
this.chargedProjectiles = add("charged_projectiles", types.itemArray());
this.bundleContents = add("bundle_contents", types.itemArray());
this.useRemainder = add("use_remainder", types.item());
}
}
@@ -0,0 +1,43 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.data.AdventureModePredicate;
import com.viaversion.viaversion.api.minecraft.item.data.AdventureModePredicate.AdventureModePredicateType1_21_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys1_21_5 extends StructuredDataKeys1_21_2 {
public final StructuredDataKey<AdventureModePredicate> canPlaceOn;
public final StructuredDataKey<AdventureModePredicate> canBreak;
public StructuredDataKeys1_21_5(final VersionedTypesHolder types) {
super(types);
final AdventureModePredicateType1_21_5 adventureModePredicateType = new AdventureModePredicateType1_21_5(types.structuredDataArray());
this.canPlaceOn = add("can_place_on", adventureModePredicateType);
this.canBreak = add("can_break", adventureModePredicateType);
this.unsupportedForOps.add(this.canPlaceOn);
this.unsupportedForOps.add(this.canBreak);
}
}
@@ -0,0 +1,50 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.type.Type;
import it.unimi.dsi.fastutil.objects.ReferenceArraySet;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public abstract class VersionedStructuredDataKeys {
private final List<StructuredDataKey<?>> keys = new ArrayList<>();
protected final Set<StructuredDataKey<?>> unsupportedForOps = new ReferenceArraySet<>();
protected <T> StructuredDataKey<T> add(final String identifier, final Type<T> type) {
final StructuredDataKey<T> key = new StructuredDataKey<>(identifier, type);
this.keys.add(key);
return key;
}
public List<StructuredDataKey<?>> keys() {
return this.keys;
}
public boolean supportsOps(final StructuredDataKey<?> key) {
return !unsupportedForOps.contains(key);
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_10 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -212,7 +201,13 @@ public class EntityTypes1_10 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -235,19 +230,25 @@ public class EntityTypes1_10 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -256,20 +257,28 @@ public class EntityTypes1_10 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_11 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -237,7 +226,13 @@ public class EntityTypes1_11 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -262,19 +257,25 @@ public class EntityTypes1_11 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -283,20 +284,28 @@ public class EntityTypes1_11 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_12 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -243,7 +232,13 @@ public class EntityTypes1_12 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -268,19 +263,25 @@ public class EntityTypes1_12 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -289,20 +290,28 @@ public class EntityTypes1_12 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_13 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -254,7 +243,13 @@ public class EntityTypes1_13 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -280,19 +275,25 @@ public class EntityTypes1_13 {
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL),
TRIDENT(94, EntityType.TRIDENT);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -301,20 +302,28 @@ public class EntityTypes1_13 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -0,0 +1,317 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entities;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.EntityTypeUtil;
import com.viaversion.viaversion.util.Key;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum EntityTypes1_21_5 implements EntityType {
ENTITY(null, null),
AREA_EFFECT_CLOUD(ENTITY),
END_CRYSTAL(ENTITY),
EVOKER_FANGS(ENTITY),
EXPERIENCE_ORB(ENTITY),
EYE_OF_ENDER(ENTITY),
FALLING_BLOCK(ENTITY),
ITEM(ENTITY),
TNT(ENTITY),
OMINOUS_ITEM_SPAWNER(ENTITY),
MARKER(ENTITY),
LIGHTNING_BOLT(ENTITY),
INTERACTION(ENTITY),
DISPLAY(ENTITY, null),
BLOCK_DISPLAY(DISPLAY),
ITEM_DISPLAY(DISPLAY),
TEXT_DISPLAY(DISPLAY),
// Hanging entities
HANGING_ENTITY(ENTITY, null),
LEASH_KNOT(HANGING_ENTITY),
PAINTING(HANGING_ENTITY),
ITEM_FRAME(HANGING_ENTITY),
GLOW_ITEM_FRAME(ITEM_FRAME),
// Projectiles
PROJECTILE(ENTITY, null),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
FISHING_BOBBER(PROJECTILE),
WITHER_SKULL(PROJECTILE),
DRAGON_FIREBALL(PROJECTILE), // Doesn't actually inherit fireball
ABSTRACT_THROWN_POTION(ITEM_PROJECTILE, null),
SPLASH_POTION(ABSTRACT_THROWN_POTION),
LINGERING_POTION(ABSTRACT_THROWN_POTION),
ABSTRACT_ARROW(PROJECTILE, null),
ARROW(ABSTRACT_ARROW),
SPECTRAL_ARROW(ABSTRACT_ARROW),
TRIDENT(ABSTRACT_ARROW),
ABSTRACT_FIREBALL(ENTITY, null),
FIREBALL(ABSTRACT_FIREBALL),
SMALL_FIREBALL(ABSTRACT_FIREBALL),
ABSTRACT_WIND_CHARGE(PROJECTILE, null),
WIND_CHARGE(ABSTRACT_WIND_CHARGE),
BREEZE_WIND_CHARGE(ABSTRACT_WIND_CHARGE),
// Vehicles
VEHICLE(ENTITY, null),
ABSTRACT_MINECART(VEHICLE, null),
MINECART(ABSTRACT_MINECART),
FURNACE_MINECART(ABSTRACT_MINECART),
COMMAND_BLOCK_MINECART(ABSTRACT_MINECART),
TNT_MINECART(ABSTRACT_MINECART),
SPAWNER_MINECART(ABSTRACT_MINECART),
ABSTRACT_MINECART_CONTAINER(ABSTRACT_MINECART, null),
CHEST_MINECART(ABSTRACT_MINECART_CONTAINER),
HOPPER_MINECART(ABSTRACT_MINECART_CONTAINER),
ABSTRACT_BOAT(VEHICLE, null),
ABSTRACT_CHEST_BOAT(ABSTRACT_BOAT, null),
ACACIA_BOAT(ABSTRACT_BOAT),
ACACIA_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
BAMBOO_CHEST_RAFT(ABSTRACT_CHEST_BOAT),
BAMBOO_RAFT(ABSTRACT_BOAT),
BIRCH_BOAT(ABSTRACT_BOAT),
BIRCH_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
CHERRY_BOAT(ABSTRACT_BOAT),
CHERRY_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
DARK_OAK_BOAT(ABSTRACT_BOAT),
DARK_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
JUNGLE_BOAT(ABSTRACT_BOAT),
JUNGLE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
MANGROVE_BOAT(ABSTRACT_BOAT),
MANGROVE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
OAK_BOAT(ABSTRACT_BOAT),
OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
PALE_OAK_BOAT(ABSTRACT_BOAT),
PALE_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
SPRUCE_BOAT(ABSTRACT_BOAT),
SPRUCE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
// Living entities as a larger subclass
LIVING_ENTITY(ENTITY, null),
ARMOR_STAND(LIVING_ENTITY),
PLAYER(LIVING_ENTITY),
// Mobs as a larger subclass
MOB(LIVING_ENTITY, null),
ENDER_DRAGON(MOB),
SLIME(MOB),
MAGMA_CUBE(SLIME),
// Ambient mobs
AMBIENT_CREATURE(MOB, null),
BAT(AMBIENT_CREATURE),
// Flying mobs
FLYING_MOB(MOB, null),
GHAST(FLYING_MOB),
PHANTOM(FLYING_MOB),
// Pathfinder mobs and its subclasses
PATHFINDER_MOB(MOB, null),
ALLAY(PATHFINDER_MOB),
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
SNOW_GOLEM(ABSTRACT_GOLEM),
IRON_GOLEM(ABSTRACT_GOLEM),
SHULKER(ABSTRACT_GOLEM),
// Ageable mobs and (tamable) animals
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
VILLAGER(ABSTRACT_VILLAGER),
WANDERING_TRADER(ABSTRACT_VILLAGER),
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
AXOLOTL(ABSTRACT_ANIMAL),
CHICKEN(ABSTRACT_ANIMAL),
PANDA(ABSTRACT_ANIMAL),
PIG(ABSTRACT_ANIMAL),
POLAR_BEAR(ABSTRACT_ANIMAL),
RABBIT(ABSTRACT_ANIMAL),
SHEEP(ABSTRACT_ANIMAL),
BEE(ABSTRACT_ANIMAL),
TURTLE(ABSTRACT_ANIMAL),
FOX(ABSTRACT_ANIMAL),
FROG(ABSTRACT_ANIMAL),
GOAT(ABSTRACT_ANIMAL),
HOGLIN(ABSTRACT_ANIMAL),
STRIDER(ABSTRACT_ANIMAL),
SNIFFER(ABSTRACT_ANIMAL),
ARMADILLO(ABSTRACT_ANIMAL),
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
COW(ABSTRACT_COW),
MOOSHROOM(ABSTRACT_COW),
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
CAT(TAMABLE_ANIMAL),
OCELOT(TAMABLE_ANIMAL),
WOLF(TAMABLE_ANIMAL),
PARROT(TAMABLE_ANIMAL),
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
HORSE(ABSTRACT_HORSE),
SKELETON_HORSE(ABSTRACT_HORSE),
ZOMBIE_HORSE(ABSTRACT_HORSE),
CAMEL(ABSTRACT_HORSE),
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
DONKEY(ABSTRACT_CHESTED_HORSE),
MULE(ABSTRACT_CHESTED_HORSE),
LLAMA(ABSTRACT_CHESTED_HORSE),
TRADER_LLAMA(LLAMA),
// Monsters
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
BLAZE(ABSTRACT_MONSTER),
CREEPER(ABSTRACT_MONSTER),
ENDERMITE(ABSTRACT_MONSTER),
ENDERMAN(ABSTRACT_MONSTER),
GIANT(ABSTRACT_MONSTER),
SILVERFISH(ABSTRACT_MONSTER),
VEX(ABSTRACT_MONSTER),
WITHER(ABSTRACT_MONSTER),
BREEZE(ABSTRACT_MONSTER),
ZOGLIN(ABSTRACT_MONSTER),
WARDEN(ABSTRACT_MONSTER),
CREAKING(ABSTRACT_MONSTER),
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
SKELETON(ABSTRACT_SKELETON),
STRAY(ABSTRACT_SKELETON),
WITHER_SKELETON(ABSTRACT_SKELETON),
BOGGED(ABSTRACT_SKELETON),
ZOMBIE(ABSTRACT_MONSTER),
DROWNED(ZOMBIE),
HUSK(ZOMBIE),
ZOMBIFIED_PIGLIN(ZOMBIE),
ZOMBIE_VILLAGER(ZOMBIE),
GUARDIAN(ABSTRACT_MONSTER),
ELDER_GUARDIAN(GUARDIAN),
SPIDER(ABSTRACT_MONSTER),
CAVE_SPIDER(SPIDER),
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
PIGLIN(ABSTRACT_PIGLIN),
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
// Water mobs
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
DOLPHIN(AGEABLE_WATER_CREATURE),
SQUID(AGEABLE_WATER_CREATURE),
GLOW_SQUID(SQUID),
WATER_ANIMAL(PATHFINDER_MOB, null),
ABSTRACT_FISH(WATER_ANIMAL, null),
PUFFERFISH(ABSTRACT_FISH),
TADPOLE(ABSTRACT_FISH),
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
COD(ABSTRACT_SCHOOLING_FISH),
SALMON(ABSTRACT_SCHOOLING_FISH),
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
// Raiders
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
WITCH(ABSTRACT_RAIDER),
RAVAGER(ABSTRACT_RAIDER),
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
VINDICATOR(ABSTRACT_ILLAGER),
PILLAGER(ABSTRACT_ILLAGER),
EVOKER(SPELLCASTER_ILLAGER),
ILLUSIONER(SPELLCASTER_ILLAGER);
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
private final EntityType parent;
private final String identifier;
private int id = -1;
EntityTypes1_21_5(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes1_21_5(final EntityType parent, @Nullable final String identifier) {
this.parent = parent;
this.identifier = identifier;
}
@Override
public int getId() {
if (id == -1) {
throw new IllegalStateException("Ids have not been initialized yet (type " + name() + ")");
}
return id;
}
@Override
public String identifier() {
Preconditions.checkArgument(identifier != null, "Called identifier method on abstract type");
return identifier;
}
@Override
public @Nullable EntityType getParent() {
return parent;
}
@Override
public boolean isAbstractType() {
return identifier == null;
}
public static EntityType getTypeFromId(final int typeId) {
return EntityTypeUtil.getTypeFromId(TYPES, typeId, PIG);
}
public static void initialize(final Protocol<?, ?, ?, ?> protocol) {
EntityTypeUtil.initialize(values(), TYPES, protocol, (type, id) -> type.id = id);
}
}
@@ -0,0 +1,318 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entities;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.EntityTypeUtil;
import com.viaversion.viaversion.util.Key;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum EntityTypes1_21_6 implements EntityType {
ENTITY(null, null),
AREA_EFFECT_CLOUD(ENTITY),
END_CRYSTAL(ENTITY),
EVOKER_FANGS(ENTITY),
EXPERIENCE_ORB(ENTITY),
EYE_OF_ENDER(ENTITY),
FALLING_BLOCK(ENTITY),
ITEM(ENTITY),
TNT(ENTITY),
OMINOUS_ITEM_SPAWNER(ENTITY),
MARKER(ENTITY),
LIGHTNING_BOLT(ENTITY),
INTERACTION(ENTITY),
DISPLAY(ENTITY, null),
BLOCK_DISPLAY(DISPLAY),
ITEM_DISPLAY(DISPLAY),
TEXT_DISPLAY(DISPLAY),
// Hanging entities
HANGING_ENTITY(ENTITY, null),
LEASH_KNOT(HANGING_ENTITY),
PAINTING(HANGING_ENTITY),
ITEM_FRAME(HANGING_ENTITY),
GLOW_ITEM_FRAME(ITEM_FRAME),
// Projectiles
PROJECTILE(ENTITY, null),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
FISHING_BOBBER(PROJECTILE),
WITHER_SKULL(PROJECTILE),
DRAGON_FIREBALL(PROJECTILE), // Doesn't actually inherit fireball
ABSTRACT_THROWN_POTION(ITEM_PROJECTILE, null),
SPLASH_POTION(ABSTRACT_THROWN_POTION),
LINGERING_POTION(ABSTRACT_THROWN_POTION),
ABSTRACT_ARROW(PROJECTILE, null),
ARROW(ABSTRACT_ARROW),
SPECTRAL_ARROW(ABSTRACT_ARROW),
TRIDENT(ABSTRACT_ARROW),
ABSTRACT_FIREBALL(ENTITY, null),
FIREBALL(ABSTRACT_FIREBALL),
SMALL_FIREBALL(ABSTRACT_FIREBALL),
ABSTRACT_WIND_CHARGE(PROJECTILE, null),
WIND_CHARGE(ABSTRACT_WIND_CHARGE),
BREEZE_WIND_CHARGE(ABSTRACT_WIND_CHARGE),
// Vehicles
VEHICLE(ENTITY, null),
ABSTRACT_MINECART(VEHICLE, null),
MINECART(ABSTRACT_MINECART),
FURNACE_MINECART(ABSTRACT_MINECART),
COMMAND_BLOCK_MINECART(ABSTRACT_MINECART),
TNT_MINECART(ABSTRACT_MINECART),
SPAWNER_MINECART(ABSTRACT_MINECART),
ABSTRACT_MINECART_CONTAINER(ABSTRACT_MINECART, null),
CHEST_MINECART(ABSTRACT_MINECART_CONTAINER),
HOPPER_MINECART(ABSTRACT_MINECART_CONTAINER),
ABSTRACT_BOAT(VEHICLE, null),
ABSTRACT_CHEST_BOAT(ABSTRACT_BOAT, null),
ACACIA_BOAT(ABSTRACT_BOAT),
ACACIA_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
BAMBOO_CHEST_RAFT(ABSTRACT_CHEST_BOAT),
BAMBOO_RAFT(ABSTRACT_BOAT),
BIRCH_BOAT(ABSTRACT_BOAT),
BIRCH_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
CHERRY_BOAT(ABSTRACT_BOAT),
CHERRY_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
DARK_OAK_BOAT(ABSTRACT_BOAT),
DARK_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
JUNGLE_BOAT(ABSTRACT_BOAT),
JUNGLE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
MANGROVE_BOAT(ABSTRACT_BOAT),
MANGROVE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
OAK_BOAT(ABSTRACT_BOAT),
OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
PALE_OAK_BOAT(ABSTRACT_BOAT),
PALE_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
SPRUCE_BOAT(ABSTRACT_BOAT),
SPRUCE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
// Living entities as a larger subclass
LIVING_ENTITY(ENTITY, null),
ARMOR_STAND(LIVING_ENTITY),
PLAYER(LIVING_ENTITY),
// Mobs as a larger subclass
MOB(LIVING_ENTITY, null),
ENDER_DRAGON(MOB),
SLIME(MOB),
MAGMA_CUBE(SLIME),
// Ambient mobs
AMBIENT_CREATURE(MOB, null),
BAT(AMBIENT_CREATURE),
// Flying mobs
FLYING_MOB(MOB, null),
GHAST(FLYING_MOB),
PHANTOM(FLYING_MOB),
// Pathfinder mobs and its subclasses
PATHFINDER_MOB(MOB, null),
ALLAY(PATHFINDER_MOB),
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
SNOW_GOLEM(ABSTRACT_GOLEM),
IRON_GOLEM(ABSTRACT_GOLEM),
SHULKER(ABSTRACT_GOLEM),
// Ageable mobs and (tamable) animals
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
VILLAGER(ABSTRACT_VILLAGER),
WANDERING_TRADER(ABSTRACT_VILLAGER),
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
AXOLOTL(ABSTRACT_ANIMAL),
CHICKEN(ABSTRACT_ANIMAL),
PANDA(ABSTRACT_ANIMAL),
PIG(ABSTRACT_ANIMAL),
POLAR_BEAR(ABSTRACT_ANIMAL),
RABBIT(ABSTRACT_ANIMAL),
SHEEP(ABSTRACT_ANIMAL),
BEE(ABSTRACT_ANIMAL),
TURTLE(ABSTRACT_ANIMAL),
FOX(ABSTRACT_ANIMAL),
FROG(ABSTRACT_ANIMAL),
GOAT(ABSTRACT_ANIMAL),
HOGLIN(ABSTRACT_ANIMAL),
STRIDER(ABSTRACT_ANIMAL),
SNIFFER(ABSTRACT_ANIMAL),
ARMADILLO(ABSTRACT_ANIMAL),
HAPPY_GHAST(ABSTRACT_ANIMAL),
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
COW(ABSTRACT_COW),
MOOSHROOM(ABSTRACT_COW),
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
CAT(TAMABLE_ANIMAL),
OCELOT(TAMABLE_ANIMAL),
WOLF(TAMABLE_ANIMAL),
PARROT(TAMABLE_ANIMAL),
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
HORSE(ABSTRACT_HORSE),
SKELETON_HORSE(ABSTRACT_HORSE),
ZOMBIE_HORSE(ABSTRACT_HORSE),
CAMEL(ABSTRACT_HORSE),
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
DONKEY(ABSTRACT_CHESTED_HORSE),
MULE(ABSTRACT_CHESTED_HORSE),
LLAMA(ABSTRACT_CHESTED_HORSE),
TRADER_LLAMA(LLAMA),
// Monsters
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
BLAZE(ABSTRACT_MONSTER),
CREEPER(ABSTRACT_MONSTER),
ENDERMITE(ABSTRACT_MONSTER),
ENDERMAN(ABSTRACT_MONSTER),
GIANT(ABSTRACT_MONSTER),
SILVERFISH(ABSTRACT_MONSTER),
VEX(ABSTRACT_MONSTER),
WITHER(ABSTRACT_MONSTER),
BREEZE(ABSTRACT_MONSTER),
ZOGLIN(ABSTRACT_MONSTER),
WARDEN(ABSTRACT_MONSTER),
CREAKING(ABSTRACT_MONSTER),
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
SKELETON(ABSTRACT_SKELETON),
STRAY(ABSTRACT_SKELETON),
WITHER_SKELETON(ABSTRACT_SKELETON),
BOGGED(ABSTRACT_SKELETON),
ZOMBIE(ABSTRACT_MONSTER),
DROWNED(ZOMBIE),
HUSK(ZOMBIE),
ZOMBIFIED_PIGLIN(ZOMBIE),
ZOMBIE_VILLAGER(ZOMBIE),
GUARDIAN(ABSTRACT_MONSTER),
ELDER_GUARDIAN(GUARDIAN),
SPIDER(ABSTRACT_MONSTER),
CAVE_SPIDER(SPIDER),
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
PIGLIN(ABSTRACT_PIGLIN),
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
// Water mobs
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
DOLPHIN(AGEABLE_WATER_CREATURE),
SQUID(AGEABLE_WATER_CREATURE),
GLOW_SQUID(SQUID),
WATER_ANIMAL(PATHFINDER_MOB, null),
ABSTRACT_FISH(WATER_ANIMAL, null),
PUFFERFISH(ABSTRACT_FISH),
TADPOLE(ABSTRACT_FISH),
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
COD(ABSTRACT_SCHOOLING_FISH),
SALMON(ABSTRACT_SCHOOLING_FISH),
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
// Raiders
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
WITCH(ABSTRACT_RAIDER),
RAVAGER(ABSTRACT_RAIDER),
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
VINDICATOR(ABSTRACT_ILLAGER),
PILLAGER(ABSTRACT_ILLAGER),
EVOKER(SPELLCASTER_ILLAGER),
ILLUSIONER(SPELLCASTER_ILLAGER);
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
private final EntityType parent;
private final String identifier;
private int id = -1;
EntityTypes1_21_6(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes1_21_6(final EntityType parent, @Nullable final String identifier) {
this.parent = parent;
this.identifier = identifier;
}
@Override
public int getId() {
if (id == -1) {
throw new IllegalStateException("Ids have not been initialized yet (type " + name() + ")");
}
return id;
}
@Override
public String identifier() {
Preconditions.checkArgument(identifier != null, "Called identifier method on abstract type");
return identifier;
}
@Override
public @Nullable EntityType getParent() {
return parent;
}
@Override
public boolean isAbstractType() {
return identifier == null;
}
public static EntityType getTypeFromId(final int typeId) {
return EntityTypeUtil.getTypeFromId(TYPES, typeId, PIG);
}
public static void initialize(final Protocol<?, ?, ?, ?> protocol) {
EntityTypeUtil.initialize(values(), TYPES, protocol, (type, id) -> type.id = id);
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_8 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -203,7 +192,13 @@ public class EntityTypes1_8 {
public enum ObjectType implements com.viaversion.viaversion.api.minecraft.entities.ObjectType {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -223,19 +218,25 @@ public class EntityTypes1_8 {
ARMOR_STAND(78, EntityType.ARMOR_STAND),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -244,20 +245,28 @@ public class EntityTypes1_8 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_9 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -211,7 +200,13 @@ public class EntityTypes1_9 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -234,19 +229,25 @@ public class EntityTypes1_9 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -255,20 +256,28 @@ public class EntityTypes1_9 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -29,5 +29,7 @@ public interface ObjectType {
int getId();
int getData();
EntityType getType();
}
@@ -22,12 +22,9 @@
*/
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_20_5 extends AbstractEntityDataTypes {
@@ -38,7 +35,7 @@ public final class EntityDataTypes1_20_5 extends AbstractEntityDataTypes {
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType itemType = add(7, Types1_20_5.ITEM);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
public final EntityDataType blockPositionType = add(10, Types.BLOCK_POSITION1_14);
@@ -63,9 +60,10 @@ public final class EntityDataTypes1_20_5 extends AbstractEntityDataTypes {
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
public EntityDataTypes1_20_5(final ParticleType particleType, final ArrayType<Particle> particlesType) {
public EntityDataTypes1_20_5(final VersionedTypesHolder types) {
super(31);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -23,14 +23,10 @@
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
@@ -66,10 +62,10 @@ public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
public EntityDataTypes1_21(final Type<Item> itemType, final ParticleType particleType, final ArrayType<Particle> particlesType) {
public EntityDataTypes1_21(final VersionedTypesHolder types) {
super(31);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -23,13 +23,10 @@
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_21_2 extends AbstractEntityDataTypes {
@@ -65,10 +62,10 @@ public final class EntityDataTypes1_21_2 extends AbstractEntityDataTypes {
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
public EntityDataTypes1_21_2(final Type<Item> itemType, final ParticleType particleType, final Type<Particle[]> particlesType) {
public EntityDataTypes1_21_2(final VersionedTypesHolder types) {
super(31);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -0,0 +1,74 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_21_5 extends AbstractEntityDataTypes {
public final EntityDataType byteType = add(0, Types.BYTE);
public final EntityDataType varIntType = add(1, Types.VAR_INT);
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
public final EntityDataType blockPositionType = add(10, Types.BLOCK_POSITION1_14);
public final EntityDataType optionalBlockPositionType = add(11, Types.OPTIONAL_POSITION_1_14);
public final EntityDataType directionType = add(12, Types.VAR_INT);
public final EntityDataType optionalUUIDType = add(13, Types.OPTIONAL_UUID);
public final EntityDataType blockStateType = add(14, Types.VAR_INT);
public final EntityDataType optionalBlockStateType = add(15, Types.VAR_INT);
public final EntityDataType compoundTagType = add(16, Types.COMPOUND_TAG);
public final EntityDataType particleType;
public final EntityDataType particlesType;
public final EntityDataType villagerDatatType = add(19, Types.VILLAGER_DATA);
public final EntityDataType optionalVarIntType = add(20, Types.OPTIONAL_VAR_INT);
public final EntityDataType poseType = add(21, Types.VAR_INT);
public final EntityDataType catVariantType = add(22, Types.VAR_INT);
public final EntityDataType cowVariantType = add(23, Types.VAR_INT);
public final EntityDataType wolfVariantType = add(24, Types.VAR_INT);
public final EntityDataType wolfSoundVariantType = add(25, Types.VAR_INT);
public final EntityDataType frogVariantType = add(26, Types.VAR_INT);
public final EntityDataType pigVariantType = add(27, Types.VAR_INT);
public final EntityDataType chickenVariantType = add(28, Types.VAR_INT);
public final EntityDataType optionalGlobalPosition = add(29, Types.OPTIONAL_GLOBAL_POSITION);
public final EntityDataType paintingVariantType = add(30, PaintingVariant.TYPE1_21_2);
public final EntityDataType snifferState = add(31, Types.VAR_INT);
public final EntityDataType armadilloState = add(32, Types.VAR_INT);
public final EntityDataType vector3FType = add(33, Types.VECTOR3F);
public final EntityDataType quaternionType = add(34, Types.QUATERNION);
public EntityDataTypes1_21_5(final VersionedTypesHolder types) {
super(35);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -0,0 +1,45 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.IntSet;
/**
* Item that does not hold any real data outside of its id and amount.
* Instead, it holds hashes of added data and a set of keys of removed data.
* <p>
* This stores the raw int identifiers instead of data keys to simplify handling across protocols
* under the assumption that the keys are almost never needed beyond automated id updating.
*
* @see Item
*/
public interface HashedItem extends ItemBase {
Int2IntMap dataHashesById();
IntSet removedDataIds();
@Override
HashedItem copy();
}
@@ -0,0 +1,115 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
public class HashedStructuredItem implements HashedItem {
private final Int2IntMap dataHashes;
private final IntSet removedData;
private int identifier;
private int amount;
public HashedStructuredItem(final int identifier, final int amount) {
this(identifier, amount, new Int2IntOpenHashMap(0), new IntOpenHashSet(0));
}
public HashedStructuredItem(final int identifier, final int amount, final Int2IntMap dataHashes, final IntSet removedData) {
this.identifier = identifier;
this.amount = amount;
this.dataHashes = dataHashes;
this.removedData = removedData;
}
public static HashedStructuredItem empty() {
// Data is mutable, create a new item
return new HashedStructuredItem(0, 0);
}
@Override
public int identifier() {
return this.identifier;
}
@Override
public void setIdentifier(final int identifier) {
this.identifier = identifier;
}
@Override
public int amount() {
return this.amount;
}
@Override
public void setAmount(final int amount) {
this.amount = amount;
}
@Override
public Int2IntMap dataHashesById() {
return this.dataHashes;
}
@Override
public IntSet removedDataIds() {
return this.removedData;
}
@Override
public HashedItem copy() {
return new HashedStructuredItem(identifier, amount, new Int2IntOpenHashMap(dataHashes), new IntOpenHashSet(removedData));
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final HashedStructuredItem that = (HashedStructuredItem) o;
if (identifier != that.identifier) return false;
if (amount != that.amount) return false;
return dataHashes.equals(that.dataHashes) && removedData.equals(that.removedData);
}
@Override
public int hashCode() {
int result = dataHashes.hashCode();
result = 31 * result + removedData.hashCode();
result = 31 * result + identifier;
result = 31 * result + amount;
return result;
}
@Override
public String toString() {
return "HashedStructuredItem{" +
"data=Hashes" + dataHashes +
", removedData=" + removedData +
", identifier=" + identifier +
", amount=" + amount +
'}';
}
}
@@ -24,37 +24,10 @@ package com.viaversion.viaversion.api.minecraft.item;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.util.Copyable;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface Item {
/**
* Returns the item identifier.
*
* @return item identifier
*/
int identifier();
/**
* Sets the item identifier.
*
* @param identifier item identifier
*/
void setIdentifier(int identifier);
/**
* Returns the item amount.
*
* @return item amount
*/
int amount();
/**
* Returns the item amount.
*
* @param amount item amount
*/
void setAmount(int amount);
public interface Item extends ItemBase {
/**
* Returns the item data. Always 0 for 1.13+ items.
@@ -102,14 +75,6 @@ public interface Item {
*
* @return copy of the item
*/
@Override
Item copy();
/**
* Returns true if the item is empty.
*
* @return true if the item is empty
*/
default boolean isEmpty() {
return identifier() == 0 || amount() <= 0;
}
}
@@ -0,0 +1,72 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
import com.viaversion.viaversion.util.Copyable;
/**
* @see Item
* @see HashedItem
*/
public interface ItemBase extends Copyable {
/**
* Returns the item identifier.
*
* @return item identifier
*/
int identifier();
/**
* Sets the item identifier.
*
* @param identifier item identifier
*/
void setIdentifier(int identifier);
/**
* Returns the item amount.
*
* @return item amount
*/
int amount();
/**
* Returns the item amount.
*
* @param amount item amount
*/
void setAmount(int amount);
/**
* Returns true if the item is empty.
*
* @return true if the item is empty
*/
default boolean isEmpty() {
return identifier() == 0 || amount() <= 0;
}
@Override
ItemBase copy();
}
@@ -22,32 +22,68 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record AdventureModePredicate(BlockPredicate[] predicates, boolean showInTooltip) {
public record AdventureModePredicate(BlockPredicate[] predicates,
boolean showInTooltip) implements Copyable, Rewritable {
public static final Type<AdventureModePredicate> TYPE = new Type<>(AdventureModePredicate.class) {
public AdventureModePredicate(final BlockPredicate[] predicates) {
this(predicates, true);
}
public static final Type<AdventureModePredicate> TYPE1_20_5 = new Type<>(AdventureModePredicate.class) {
@Override
public AdventureModePredicate read(final ByteBuf buffer) {
final BlockPredicate[] predicates = BlockPredicate.ARRAY_TYPE.read(buffer);
final BlockPredicate[] predicates = BlockPredicate.ARRAY_TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new AdventureModePredicate(predicates, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final AdventureModePredicate value) {
BlockPredicate.ARRAY_TYPE.write(buffer, value.predicates);
BlockPredicate.ARRAY_TYPE1_20_5.write(buffer, value.predicates);
buffer.writeBoolean(value.showInTooltip);
}
};
public AdventureModePredicate rewrite(final Int2IntFunction blockIdRewriter) {
public static final class AdventureModePredicateType1_21_5 extends Type<AdventureModePredicate> {
private final Type<BlockPredicate[]> blockPredicateType;
public AdventureModePredicateType1_21_5(final Type<StructuredData<?>[]> dataArrayType) {
super(AdventureModePredicate.class);
this.blockPredicateType = new ArrayType<>(new BlockPredicate.BlockPredicateType1_21_5(dataArrayType));
}
@Override
public AdventureModePredicate read(final ByteBuf buffer) {
final BlockPredicate[] predicates = blockPredicateType.read(buffer);
return new AdventureModePredicate(predicates);
}
@Override
public void write(final ByteBuf buffer, final AdventureModePredicate value) {
blockPredicateType.write(buffer, value.predicates);
}
}
@Override
public AdventureModePredicate rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final BlockPredicate[] predicates = new BlockPredicate[this.predicates.length];
for (int i = 0; i < predicates.length; i++) {
predicates[i] = this.predicates[i].rewrite(blockIdRewriter);
predicates[i] = this.predicates[i].rewrite(connection, protocol, clientbound);
}
return new AdventureModePredicate(predicates, showInTooltip);
}
@Override
public AdventureModePredicate copy() {
return new AdventureModePredicate(Copyable.copy(predicates), showInTooltip);
}
}
@@ -22,18 +22,25 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern, boolean showInTooltip) {
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern,
boolean showInTooltip) implements Rewritable {
public ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern) {
this(material, pattern, true);
}
public static final Type<ArmorTrim> TYPE1_20_5 = new Type<>(ArmorTrim.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_20_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -41,7 +48,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_20_5.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
@@ -49,7 +56,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_2.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -57,7 +64,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_2.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
@@ -65,7 +72,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_4.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -73,20 +80,35 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_4.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_5 = new Type<>(ArmorTrim.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_21_5.read(buffer);
return new ArmorTrim(material, pattern);
}
public ArmorTrim rewrite(final Int2IntFunction idRewriteFunction) {
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_5.write(buffer, value.material);
ArmorTrimPattern.TYPE1_21_5.write(buffer, value.pattern);
}
};
@Override
public ArmorTrim rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimMaterial> material = this.material;
if (material.isDirect()) {
material = Holder.of(material.value().rewrite(idRewriteFunction));
material = Holder.of(material.value().rewrite(connection, protocol, clientbound));
}
Holder<ArmorTrimPattern> pattern = this.pattern;
if (pattern.isDirect()) {
pattern = Holder.of(pattern.value().rewrite(idRewriteFunction));
pattern = Holder.of(pattern.value().rewrite(connection, protocol, clientbound));
}
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -23,20 +23,28 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.util.Map;
public record ArmorTrimMaterial(String assetName, int itemId, float itemModelIndex,
Map<String, String> overrideArmorMaterials, Tag description) {
Map<String, String> overrideArmorMaterials,
Tag description) implements Copyable, Rewritable {
public ArmorTrimMaterial(final String assetName, final int itemId, final Map<String, String> overrideArmorMaterials, final Tag description) {
this(assetName, itemId, 0F, overrideArmorMaterials, description);
}
public ArmorTrimMaterial(final String assetName, final Map<String, String> overrideArmorMaterials, final Tag description) {
this(assetName, 0, 0F, overrideArmorMaterials, description);
}
public static final HolderType<ArmorTrimMaterial> TYPE1_20_5 = new HolderType<>() {
// The override key is an int, but given we don't use it at all and that creating a new type is annoying,
// we'll just store it in the string map:tm:
@@ -47,7 +55,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final int key = Types.VAR_INT.readPrimitive(buffer);
final String value = Types.STRING.read(buffer);
@@ -73,7 +81,6 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_2 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
@@ -82,7 +89,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
@@ -108,7 +115,6 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_4 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
@@ -116,7 +122,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
final int item = Types.VAR_INT.readPrimitive(buffer);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
@@ -141,8 +147,44 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_5 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
public ArmorTrimMaterial rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimMaterial(assetName, idRewriteFunction.applyAsInt(itemId), itemModelIndex, overrideArmorMaterials, description);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
overrideArmorMaterials.put(key, value);
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
Types.STRING.write(buffer, entry.getKey());
Types.STRING.write(buffer, entry.getValue());
}
Types.TAG.write(buffer, value.description());
}
};
@Override
public ArmorTrimMaterial rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new ArmorTrimMaterial(assetName, Rewritable.rewriteItem(protocol, clientbound, itemId), itemModelIndex, overrideArmorMaterials, description);
}
@Override
public ArmorTrimMaterial copy() {
return new ArmorTrimMaterial(assetName, itemId, itemModelIndex, new Object2ObjectArrayMap<>(overrideArmorMaterials), description);
}
}
@@ -23,14 +23,21 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrimPattern(String assetName, int itemId, Tag description, boolean decal) {
public record ArmorTrimPattern(String assetName, int itemId, Tag description, boolean decal) implements Copyable, Rewritable {
public static final HolderType<ArmorTrimPattern> TYPE = new HolderType<>() {
public ArmorTrimPattern(final String assetName, final Tag description, final boolean decal) {
this(assetName, 0, description, decal);
}
public static final HolderType<ArmorTrimPattern> TYPE1_20_5 = new HolderType<>() {
@Override
public ArmorTrimPattern readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
@@ -48,8 +55,30 @@ public record ArmorTrimPattern(String assetName, int itemId, Tag description, bo
buffer.writeBoolean(value.decal());
}
};
public static final HolderType<ArmorTrimPattern> TYPE1_21_5 = new HolderType<>() {
@Override
public ArmorTrimPattern readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final Tag description = Types.TAG.read(buffer);
final boolean decal = buffer.readBoolean();
return new ArmorTrimPattern(assetName, description, decal);
}
public ArmorTrimPattern rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimPattern(assetName, idRewriteFunction.applyAsInt(itemId), description, decal);
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimPattern value) {
Types.STRING.write(buffer, value.assetName());
Types.TAG.write(buffer, value.description());
buffer.writeBoolean(value.decal());
}
};
@Override
public ArmorTrimPattern rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new ArmorTrimPattern(assetName, Rewritable.rewriteItem(protocol, clientbound, itemId), description, decal);
}
@Override
public ArmorTrimPattern copy() {
return new ArmorTrimPattern(assetName, itemId, description.copy(), decal);
}
}
@@ -25,10 +25,11 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean showInTooltip) {
public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean showInTooltip) implements Copyable {
public static final Type<AttributeModifiers1_20_5> TYPE = new Type<>(AttributeModifiers1_20_5.class) {
@Override
@@ -45,6 +46,11 @@ public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean sh
}
};
@Override
public AttributeModifiers1_20_5 copy() {
return new AttributeModifiers1_20_5(Copyable.copy(modifiers), showInTooltip);
}
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
@@ -22,41 +22,94 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) {
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) implements Copyable {
public static final Type<AttributeModifiers1_21> TYPE = new Type<>(AttributeModifiers1_21.class) {
public AttributeModifiers1_21(final AttributeModifier[] modifiers) {
this(modifiers, true);
}
public static final Type<AttributeModifiers1_21> TYPE1_21 = new Type<>(AttributeModifiers1_21.class) {
@Override
public AttributeModifiers1_21 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE.read(buffer);
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE1_21.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new AttributeModifiers1_21(modifiers, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_21 value) {
AttributeModifier.ARRAY_TYPE.write(buffer, value.modifiers());
AttributeModifier.ARRAY_TYPE1_21.write(buffer, value.modifiers());
buffer.writeBoolean(value.showInTooltip());
}
};
public static final Type<AttributeModifiers1_21> TYPE1_21_5 = new Type<>(AttributeModifiers1_21.class) {
@Override
public AttributeModifiers1_21 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE1_21.read(buffer);
return new AttributeModifiers1_21(modifiers);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_21 value) {
AttributeModifier.ARRAY_TYPE1_21.write(buffer, value.modifiers());
}
@Override
public void write(final Ops ops, final AttributeModifiers1_21 value) {
ops.write(AttributeModifier.ARRAY_TYPE1_21, value.modifiers);
}
};
public static final Type<AttributeModifiers1_21> TYPE1_21_6 = new Type<>(AttributeModifiers1_21.class) {
@Override
public AttributeModifiers1_21 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE1_21_6.read(buffer);
return new AttributeModifiers1_21(modifiers);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_21 value) {
AttributeModifier.ARRAY_TYPE1_21_6.write(buffer, value.modifiers());
}
@Override
public void write(final Ops ops, final AttributeModifiers1_21 value) {
ops.write(AttributeModifier.ARRAY_TYPE1_21_6, value.modifiers);
}
};
public AttributeModifiers1_21 rewrite(final Int2IntFunction rewriteFunction) {
final AttributeModifier[] modifiers = new AttributeModifier[this.modifiers.length];
for (int i = 0; i < this.modifiers.length; i++) {
final AttributeModifier modifier = this.modifiers[i];
modifiers[i] = new AttributeModifier(rewriteFunction.applyAsInt(modifier.attribute()), modifier.modifier(), modifier.slotType());
modifiers[i] = new AttributeModifier(rewriteFunction.applyAsInt(modifier.attribute()), modifier.modifier(), modifier.slotType(), modifier.display());
}
return new AttributeModifiers1_21(modifiers, showInTooltip);
}
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
@Override
public AttributeModifiers1_21 copy() {
return new AttributeModifiers1_21(Copyable.copy(modifiers), showInTooltip);
}
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
public record AttributeModifier(int attribute, ModifierData modifier, int slotType, Display display) {
private static final String[] EQUIPMENT_SLOT_GROUPS = {"any", "mainhand", "offhand", "hand", "feet", "legs", "chest", "head", "armor", "body", "saddle"};
private static final String[] OPERATION = {"add_value", "add_multiplied_base", "add_multiplied_total"};
public AttributeModifier(final int attribute, final ModifierData modifier, final int slotType) {
this(attribute, modifier, slotType, Display.DEFAULT);
}
public static final Type<AttributeModifier> TYPE1_21 = new Type<>(AttributeModifier.class) {
@Override
public AttributeModifier read(final ByteBuf buffer) {
final int attribute = Types.VAR_INT.readPrimitive(buffer);
@@ -71,8 +124,62 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
ModifierData.TYPE.write(buffer, value.modifier);
Types.VAR_INT.writePrimitive(buffer, value.slotType);
}
@Override
public void write(final Ops ops, final AttributeModifier value) {
final Key attribute = ops.context().registryAccess().attributeModifier(value.attribute);
ops.writeMap(map -> map
.write("type", Types.RESOURCE_LOCATION, attribute)
.write("id", Types.RESOURCE_LOCATION, Key.of(value.modifier.id()))
.write("amount", Types.DOUBLE, value.modifier.amount)
.write("operation", Types.STRING, OPERATION[value.modifier.operation()])
.writeOptional("slot", Types.STRING, EQUIPMENT_SLOT_GROUPS[value.slotType()], "any"));
}
};
public static final Type<AttributeModifier[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public static final Type<AttributeModifier[]> ARRAY_TYPE1_21 = new ArrayType<>(TYPE1_21);
public static final Type<AttributeModifier> TYPE1_21_6 = new Type<>(AttributeModifier.class) {
@Override
public AttributeModifier read(final ByteBuf buffer) {
final int attribute = Types.VAR_INT.readPrimitive(buffer);
final ModifierData modifier = ModifierData.TYPE.read(buffer);
final int slot = Types.VAR_INT.readPrimitive(buffer);
final int displayType = Types.VAR_INT.readPrimitive(buffer);
final Display display = displayType == OverrideText.ID ? new OverrideText(Types.TAG.read(buffer)) : new Display(displayType);
return new AttributeModifier(attribute, modifier, slot, display);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifier value) {
Types.VAR_INT.writePrimitive(buffer, value.attribute);
ModifierData.TYPE.write(buffer, value.modifier);
Types.VAR_INT.writePrimitive(buffer, value.slotType);
value.display.write(buffer);
}
@Override
public void write(final Ops ops, final AttributeModifier value) {
final Key attribute = ops.context().registryAccess().attributeModifier(value.attribute);
ops.writeMap(map -> {
map.write("type", Types.RESOURCE_LOCATION, attribute)
.write("id", Types.RESOURCE_LOCATION, Key.of(value.modifier.id()))
.write("amount", Types.DOUBLE, value.modifier.amount)
.write("operation", Types.STRING, OPERATION[value.modifier.operation()])
.writeOptional("slot", Types.STRING, EQUIPMENT_SLOT_GROUPS[value.slotType()], "any");
if (value.display.equals(Display.DEFAULT)) {
return;
}
map.writeMap("display", display -> {
display.write("type", Types.STRING, Display.DISPLAY_TYPES[value.display.id()]);
if (value.display instanceof final OverrideText overrideText) {
display.write("value", Types.TAG, overrideText.component);
}
});
});
}
};
public static final Type<AttributeModifier[]> ARRAY_TYPE1_21_6 = new ArrayType<>(TYPE1_21_6);
}
public record ModifierData(String id, double amount, int operation) {
@@ -94,4 +201,52 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
}
};
}
public static class Display implements Copyable {
public static final String[] DISPLAY_TYPES = {"default", "hidden", "override_text"};
public static final Display DEFAULT = new Display(0);
private final int id;
public Display(final int id) {
this.id = id;
}
public int id() {
return this.id;
}
public void write(final ByteBuf buf) {
Types.VAR_INT.writePrimitive(buf, this.id);
}
@Override
public Display copy() {
return this;
}
}
public static final class OverrideText extends Display {
public static final int ID = 2;
private final Tag component;
public OverrideText(final Tag component) {
super(ID);
this.component = component;
}
public Tag component() {
return this.component;
}
@Override
public void write(final ByteBuf buf) {
super.write(buf);
Types.TAG.write(buf, this.component);
}
@Override
public OverrideText copy() {
return new OverrideText(this.component.copy());
}
}
}
@@ -23,12 +23,14 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record Bee(CompoundTag entityData, int ticksInHive, int minTicksInHive) {
public record Bee(CompoundTag entityData, int ticksInHive, int minTicksInHive) implements Copyable {
public static final Type<Bee> TYPE = new Type<>(Bee.class) {
@Override
@@ -45,7 +47,19 @@ public record Bee(CompoundTag entityData, int ticksInHive, int minTicksInHive) {
Types.VAR_INT.writePrimitive(buffer, value.ticksInHive);
Types.VAR_INT.writePrimitive(buffer, value.minTicksInHive);
}
@Override
public void write(final Ops ops, final Bee value) {
ops.writeMap(map -> map
.writeOptional("entity_data", Types.COMPOUND_TAG, value.entityData, new CompoundTag())
.write("ticks_in_hive", Types.INT, value.ticksInHive)
.write("min_ticks_in_hive", Types.INT, value.minTicksInHive));
}
};
public static final Type<Bee[]> ARRAY_TYPE = new ArrayType<>(TYPE);
@Override
public Bee copy() {
return new Bee(entityData.copy(), ticksInHive, minTicksInHive);
}
}
@@ -23,24 +23,36 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.predicate.DataComponentMatchers;
import com.viaversion.viaversion.api.minecraft.data.predicate.DataComponentMatchers.DataComponentMatchersType;
import com.viaversion.viaversion.api.minecraft.data.predicate.DataComponentPredicate;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher @Nullable [] propertyMatchers,
@Nullable CompoundTag tag) {
@Nullable CompoundTag tag,
DataComponentMatchers dataMatchers) implements Copyable, Rewritable {
public static final Type<BlockPredicate> TYPE = new Type<>(BlockPredicate.class) {
public BlockPredicate(@Nullable final HolderSet holderSet, final StatePropertyMatcher @Nullable [] propertyMatchers, @Nullable final CompoundTag tag) {
this(holderSet, propertyMatchers, tag, new DataComponentMatchers(new StructuredData[0], new DataComponentPredicate[0]));
}
public static final Type<BlockPredicate> TYPE1_20_5 = new Type<>(BlockPredicate.class) {
@Override
public BlockPredicate read(final ByteBuf buffer) {
final HolderSet holders = Types.OPTIONAL_HOLDER_SET.read(buffer);
final StatePropertyMatcher[] propertyMatchers = buffer.readBoolean() ? StatePropertyMatcher.ARRAY_TYPE.read(buffer) : null;
final CompoundTag tag = Types.OPTIONAL_COMPOUND_TAG.read(buffer);
return new BlockPredicate(holders, propertyMatchers, tag);
return new BlockPredicate(holders, propertyMatchers, tag, null);
}
@Override
@@ -55,14 +67,51 @@ public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher
Types.OPTIONAL_COMPOUND_TAG.write(buffer, value.tag);
}
};
public static final Type<BlockPredicate[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public static final Type<BlockPredicate[]> ARRAY_TYPE1_20_5 = new ArrayType<>(TYPE1_20_5);
public BlockPredicate rewrite(final Int2IntFunction blockIdRewriter) {
public static final class BlockPredicateType1_21_5 extends Type<BlockPredicate> {
private final Type<DataComponentMatchers> matchersType;
public BlockPredicateType1_21_5(final Type<StructuredData<?>[]> dataArrayType) {
super(BlockPredicate.class);
this.matchersType = new DataComponentMatchersType(dataArrayType);
}
@Override
public BlockPredicate read(final ByteBuf buffer) {
final HolderSet holders = Types.OPTIONAL_HOLDER_SET.read(buffer);
final StatePropertyMatcher[] propertyMatchers = buffer.readBoolean() ? StatePropertyMatcher.ARRAY_TYPE.read(buffer) : null;
final CompoundTag tag = Types.OPTIONAL_COMPOUND_TAG.read(buffer);
final DataComponentMatchers matchers = matchersType.read(buffer);
return new BlockPredicate(holders, propertyMatchers, tag, matchers);
}
@Override
public void write(final ByteBuf buffer, final BlockPredicate value) {
Types.OPTIONAL_HOLDER_SET.write(buffer, value.holderSet);
buffer.writeBoolean(value.propertyMatchers != null);
if (value.propertyMatchers != null) {
StatePropertyMatcher.ARRAY_TYPE.write(buffer, value.propertyMatchers);
}
Types.OPTIONAL_COMPOUND_TAG.write(buffer, value.tag);
matchersType.write(buffer, value.dataMatchers);
}
}
@Override
public BlockPredicate rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (holderSet == null || holderSet.hasTagKey()) {
return this;
}
final HolderSet updatedHolders = holderSet.rewrite(blockIdRewriter);
final HolderSet updatedHolders = holderSet.rewrite(Rewritable.blockRewriteFunction(protocol, clientbound));
return new BlockPredicate(updatedHolders, propertyMatchers, tag);
}
@Override
public BlockPredicate copy() {
return new BlockPredicate(holderSet, Copyable.copy(propertyMatchers), tag == null ? null : tag.copy());
}
}
@@ -22,19 +22,21 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.Map;
public record BlockStateProperties(Map<String, String> properties) {
public record BlockStateProperties(Map<String, String> properties) implements Copyable {
public static final Type<BlockStateProperties> TYPE = new Type<>(BlockStateProperties.class) {
@Override
public BlockStateProperties read(final ByteBuf buffer) {
final int size = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> properties = new Object2ObjectOpenHashMap<>(size);
final Map<String, String> properties = new Object2ObjectOpenHashMap<>();
for (int i = 0; i < size; i++) {
properties.put(Types.STRING.read(buffer), Types.STRING.read(buffer));
}
@@ -49,6 +51,19 @@ public record BlockStateProperties(Map<String, String> properties) {
Types.STRING.write(buffer, entry.getValue());
}
}
@Override
public void write(final Ops ops, final BlockStateProperties value) {
ops.writeMap(map -> {
for (final Map.Entry<String, String> entry : value.properties.entrySet()) {
map.write(Types.STRING, entry.getKey(), Types.STRING, entry.getValue());
}
});
}
};
@Override
public BlockStateProperties copy() {
return new BlockStateProperties(new Object2ObjectOpenHashMap<>(properties));
}
}
@@ -0,0 +1,114 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record BlocksAttacks(
float blockDelaySeconds,
float disableCooldownScale,
DamageReduction[] damageReductions,
ItemDamageFunction itemDamage,
@Nullable String bypassedByTag,
@Nullable Holder<SoundEvent> blockSound,
@Nullable Holder<SoundEvent> disableSound
) {
public static final Type<BlocksAttacks> TYPE = new Type<>(BlocksAttacks.class) {
@Override
public BlocksAttacks read(final ByteBuf buffer) {
final float blockDelaySeconds = buffer.readFloat();
final float disableCooldownScale = buffer.readFloat();
final DamageReduction[] damageReductions = DamageReduction.ARRAY_TYPE.read(buffer);
final ItemDamageFunction itemDamage = ItemDamageFunction.TYPE.read(buffer);
final String bypassedByTag = Types.OPTIONAL_STRING.read(buffer);
final Holder<SoundEvent> blockSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
final Holder<SoundEvent> disableSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
return new BlocksAttacks(blockDelaySeconds, disableCooldownScale, damageReductions, itemDamage, bypassedByTag, blockSound, disableSound);
}
@Override
public void write(final ByteBuf buffer, final BlocksAttacks value) {
buffer.writeFloat(value.blockDelaySeconds());
buffer.writeFloat(value.disableCooldownScale());
DamageReduction.ARRAY_TYPE.write(buffer, value.damageReductions());
ItemDamageFunction.TYPE.write(buffer, value.itemDamage());
Types.OPTIONAL_STRING.write(buffer, value.bypassedByTag());
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.blockSound());
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.disableSound());
}
};
public record DamageReduction(float horizontalBlockingAngle, @Nullable HolderSet type, float base, float factor) {
public static final Type<DamageReduction> TYPE = new Type<>(DamageReduction.class) {
@Override
public DamageReduction read(final ByteBuf buffer) {
final float horizontalBlockingAngle = buffer.readFloat();
final HolderSet type = Types.OPTIONAL_HOLDER_SET.read(buffer);
final float base = buffer.readFloat();
final float factor = buffer.readFloat();
return new DamageReduction(horizontalBlockingAngle, type, base, factor);
}
@Override
public void write(final ByteBuf buffer, final DamageReduction value) {
buffer.writeFloat(value.horizontalBlockingAngle());
Types.OPTIONAL_HOLDER_SET.write(buffer, value.type());
buffer.writeFloat(value.base());
buffer.writeFloat(value.factor());
}
};
public static final ArrayType<DamageReduction> ARRAY_TYPE = new ArrayType<>(TYPE);
}
public record ItemDamageFunction(float threshold, float base, float factor) {
public static final Type<ItemDamageFunction> TYPE = new Type<>(ItemDamageFunction.class) {
@Override
public ItemDamageFunction read(final ByteBuf buffer) {
final float threshold = buffer.readFloat();
final float base = buffer.readFloat();
final float factor = buffer.readFloat();
return new ItemDamageFunction(threshold, base, factor);
}
@Override
public void write(final ByteBuf buffer, final ItemDamageFunction value) {
buffer.writeFloat(value.threshold());
buffer.writeFloat(value.base());
buffer.writeFloat(value.factor());
}
};
}
}
@@ -26,9 +26,10 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration narrationDecoration) {
public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration narrationDecoration) implements Copyable {
public static final HolderType<ChatType> TYPE = new HolderType<>() {
@Override
@@ -45,7 +46,12 @@ public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration nar
}
};
public record ChatTypeDecoration(String translationKey, int[] parameters, Tag style) {
@Override
public ChatType copy() {
return new ChatType(chatDecoration.copy(), narrationDecoration.copy());
}
public record ChatTypeDecoration(String translationKey, int[] parameters, Tag style) implements Copyable {
public static final Type<ChatTypeDecoration> TYPE = new Type<>(ChatTypeDecoration.class) {
@@ -64,5 +70,10 @@ public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration nar
Types.TAG.write(buffer, value.style());
}
};
@Override
public ChatTypeDecoration copy() {
return new ChatTypeDecoration(translationKey, parameters.clone(), style.copy());
}
}
}
@@ -22,15 +22,20 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
boolean hasConsumeParticles, ConsumeEffect<?>[] consumeEffects) {
boolean hasConsumeParticles,
ConsumeEffect<?>[] consumeEffects) implements Copyable, Rewritable {
public static final Type<?>[] EFFECT_TYPES = {
ApplyStatusEffects.TYPE,
@@ -108,4 +113,15 @@ public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<S
}
};
}
@Override
public Consumable1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundHolder = this.sound.updateId(Rewritable.soundRewriteFunction(protocol, clientbound));
return soundHolder == this.sound ? this : new Consumable1_21_2(consumeSeconds, animationType, soundHolder, hasConsumeParticles, consumeEffects);
}
@Override
public Consumable1_21_2 copy() {
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, Copyable.copy(consumeEffects));
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
public final class ContainterContents {
// Just write it as Item[] directly, makes processing easier (until op reading is needed)
public static final class ContainerContentsType extends ArrayType<Item> {
private final Type<Item> itemType;
public ContainerContentsType(final Type<Item> itemType) {
super(itemType, 256);
this.itemType = itemType;
}
@Override
public void write(final Ops ops, final Item[] value) {
ops.writeList(list -> {
for (int i = 0; i < value.length; i++) {
final Item item = value[i];
final int slot = i;
list.writeMap(map -> map
.write("slot", Types.INT, slot)
.write("item", itemType, item));
}
});
}
}
}
@@ -22,11 +22,16 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.ArrayUtil;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[] strings, int[] colors) {
public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[] strings,
int[] colors) implements Copyable {
public static final Type<CustomModelData1_21_4> TYPE = new Type<>(CustomModelData1_21_4.class) {
@Override
@@ -45,5 +50,19 @@ public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[]
Types.STRING_ARRAY.write(buffer, value.strings());
Types.INT_ARRAY_PRIMITIVE.write(buffer, value.colors());
}
@Override
public void write(final Ops ops, final CustomModelData1_21_4 value) {
ops.writeMap(map -> map
.writeOptional("floats", new ArrayType<>(Types.FLOAT), ArrayUtil.boxedArray(value.floats), new Float[0])
.writeOptional("flags", new ArrayType<>(Types.BOOLEAN), ArrayUtil.boxedArray(value.booleans), new Boolean[0])
.writeOptional("strings", Types.STRING_ARRAY, value.strings(), new String[0])
.writeOptional("colors", new ArrayType<>(Types.INT), ArrayUtil.boxedArray(value.colors), new Integer[0]));
}
};
@Override
public CustomModelData1_21_4 copy() {
return new CustomModelData1_21_4(Copyable.copy(floats), Copyable.copy(booleans), Copyable.copy(strings), Copyable.copy(colors));
}
}
@@ -22,22 +22,29 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
public record DamageResistant(String typesTagKey) {
public record DamageResistant(Key typesTagKey) {
public static final Type<DamageResistant> TYPE = new Type<>(DamageResistant.class) {
@Override
public DamageResistant read(final ByteBuf buffer) {
final String typesTagKey = Types.STRING.read(buffer);
final Key typesTagKey = Types.RESOURCE_LOCATION.read(buffer);
return new DamageResistant(typesTagKey);
}
@Override
public void write(final ByteBuf buffer, final DamageResistant value) {
Types.STRING.write(buffer, value.typesTagKey());
Types.RESOURCE_LOCATION.write(buffer, value.typesTagKey());
}
@Override
public void write(final Ops ops, final DamageResistant value) {
ops.writeMap(map -> map.write("types", Types.TAG_KEY, value.typesTagKey));
}
};
}
@@ -24,10 +24,10 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2.ConsumeEffect;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record DeathProtection(ConsumeEffect<?>[] deathEffects) {
public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyable {
public static final Type<DeathProtection> TYPE = new Type<>(DeathProtection.class) {
@Override
@@ -41,4 +41,9 @@ public record DeathProtection(ConsumeEffect<?>[] deathEffects) {
ConsumeEffect.ARRAY_TYPE.write(buffer, value.deathEffects);
}
};
@Override
public DeathProtection copy() {
return new DeathProtection(Copyable.copy(deathEffects));
}
}
@@ -22,12 +22,18 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record DyedColor(int rgb, boolean showInTooltip) {
public static final Type<DyedColor> TYPE = new Type<>(DyedColor.class) {
public DyedColor(final int rgb) {
this(rgb, true);
}
public static final Type<DyedColor> TYPE1_20_5 = new Type<>(DyedColor.class) {
@Override
public DyedColor read(final ByteBuf buffer) {
final int rgb = buffer.readInt();
@@ -41,5 +47,21 @@ public record DyedColor(int rgb, boolean showInTooltip) {
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<DyedColor> TYPE1_21_5 = new Type<>(DyedColor.class) {
@Override
public DyedColor read(final ByteBuf buffer) {
final int rgb = buffer.readInt();
return new DyedColor(rgb);
}
@Override
public void write(final ByteBuf buffer, final DyedColor value) {
buffer.writeInt(value.rgb);
}
@Override
public void write(final Ops ops, final DyedColor dyedColor) {
ops.write(Types.INT, dyedColor.rgb);
}
};
}
@@ -20,26 +20,29 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.chunk.ChunkSectionType1_8;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType1_8;
import java.util.List;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public final class Types1_8 {
public record Enchantable(int value) {
/**
* Entity data type for 1.8
*/
public static final Type<EntityData> ENTITY_DATA = new EntityDataType1_8();
/**
* Entity data list type for 1.8
*/
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
public static final Type<Enchantable> TYPE = new Type<>(Enchantable.class) {
@Override
public Enchantable read(final ByteBuf buffer) {
return new Enchantable(Types.VAR_INT.readPrimitive(buffer));
}
public static final Type<ChunkSection> CHUNK_SECTION = new ChunkSectionType1_8();
@Override
public void write(final ByteBuf buffer, final Enchantable value) {
Types.VAR_INT.writePrimitive(buffer, value.value);
}
@Override
public void write(final Ops ops, final Enchantable enchantable) {
ops.writeMap(map -> map.write("value", Types.INT, enchantable.value));
}
};
}
@@ -22,15 +22,22 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) {
public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) implements Copyable {
public static final Type<Enchantments> TYPE = new Type<>(Enchantments.class) {
public Enchantments(final Int2IntMap enchantments) {
this(enchantments, true);
}
public static final Type<Enchantments> TYPE1_20_5 = new Type<>(Enchantments.class) {
@Override
public Enchantments read(final ByteBuf buffer) {
final Int2IntMap enchantments = new Int2IntOpenHashMap();
@@ -54,6 +61,39 @@ public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) {
buffer.writeBoolean(value.showInTooltip());
}
};
public static final Type<Enchantments> TYPE1_21_5 = new Type<>(Enchantments.class) {
@Override
public Enchantments read(final ByteBuf buffer) {
final Int2IntMap enchantments = new Int2IntOpenHashMap();
final int size = Types.VAR_INT.readPrimitive(buffer);
for (int i = 0; i < size; i++) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final int level = Types.VAR_INT.readPrimitive(buffer);
enchantments.put(id, level);
}
return new Enchantments(enchantments);
}
@Override
public void write(final ByteBuf buffer, final Enchantments value) {
Types.VAR_INT.writePrimitive(buffer, value.enchantments.size());
for (final Int2IntMap.Entry entry : value.enchantments.int2IntEntrySet()) {
Types.VAR_INT.writePrimitive(buffer, entry.getIntKey());
Types.VAR_INT.writePrimitive(buffer, entry.getIntValue());
}
}
@Override
public void write(final Ops ops, final Enchantments value) {
ops.writeMap(map -> {
for (final Int2IntMap.Entry entry : value.enchantments.int2IntEntrySet()) {
final Key key = ops.context().registryAccess().enchantment(entry.getIntKey());
map.write(Types.RESOURCE_LOCATION, key, Types.VAR_INT, entry.getIntValue());
}
});
}
};
public Enchantments(final boolean showInTooltip) {
this(new Int2IntOpenHashMap(), showInTooltip);
@@ -78,4 +118,9 @@ public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) {
public int getLevel(final int id) {
return enchantments.getOrDefault(id, -1);
}
@Override
public Enchantments copy() {
return new Enchantments(new Int2IntOpenHashMap(enchantments), showInTooltip);
}
}
@@ -0,0 +1,51 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.types.EnumType;
import com.viaversion.viaversion.api.type.types.EnumType.Fallback;
import com.viaversion.viaversion.api.type.types.FakeEnumType;
import com.viaversion.viaversion.api.type.types.RegistryValueType;
import java.util.List;
import static com.viaversion.viaversion.api.type.types.FakeEnumType.Entry.of;
/**
* Enum types that aren't associated with any specific item data in this package.
*/
public final class EnumTypes {
public static final EnumType DYE_COLOR = new EnumType("white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray", "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black");
public static final EnumType RARITY = new EnumType("common", "uncommon", "rare", "epic");
public static final EnumType FOX_VARIANT = new EnumType("red", "snow");
public static final EnumType SALMON_VARIANT = new EnumType(Fallback.CLAMP, "small", "medium", "large");
public static final EnumType PARROT_VARIANT = new EnumType(Fallback.CLAMP, "red_blue", "blue", "green", "yellow_blue", "gray");
public static final EnumType MUSHROOM_COW_VARIANT = new EnumType(Fallback.CLAMP, "red", "brown");
public static final EnumType HORSE_VARIANT = new EnumType(Fallback.WRAP, "white", "creamy", "chestnut", "brown", "black", "gray", "dark_brown");
public static final EnumType LLAMA_VARIANT = new EnumType(Fallback.CLAMP, "creamy", "white", "brown", "gray");
public static final EnumType AXOLOTL_VARIANT = new EnumType("lucy", "wild", "gold", "cyan", "blue");
// Enums with non-ordinal ids
public static final FakeEnumType RABBIT_VARIANT = new FakeEnumType(List.of("brown", "white", "black", "white_splotched", "gold", "salt"), of(99, "evil"));
// Pretty much enums, but with a resource location
public static final RegistryValueType VILLAGER_TYPE = new RegistryValueType("desert", "jungle", "plains", "savanna", "snow", "swamp", "taiga");
}
@@ -22,20 +22,33 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Nullable String model,
@Nullable String cameraOverlay, @Nullable HolderSet allowedEntities, boolean dispensable,
boolean swappable, boolean damageOnHurt) {
boolean swappable, boolean damageOnHurt, boolean equipOnInteract,
boolean canBeSheared, Holder<SoundEvent> shearingSound) implements Rewritable {
public static final Type<Equippable> TYPE = new Type<>(Equippable.class) {
public Equippable(final int equipmentSlot, final Holder<SoundEvent> soundEvent, @Nullable final String model, @Nullable final String cameraOverlay,
@Nullable final HolderSet allowedEntities, final boolean dispensable, final boolean swappable, final boolean damageOnHurt) {
this(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, true);
}
public Equippable(final int equipmentSlot, final Holder<SoundEvent> soundEvent, @Nullable final String model, @Nullable final String cameraOverlay,
@Nullable final HolderSet allowedEntities, final boolean dispensable, final boolean swappable, final boolean damageOnHurt, final boolean equipOnInteract) {
this(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract, false, Holder.of(0));
}
public static final Type<Equippable> TYPE1_21_2 = new Type<>(Equippable.class) {
@Override
public Equippable read(final ByteBuf buffer) {
final int equipmentSlot = Types.VAR_INT.readPrimitive(buffer);
@@ -61,9 +74,71 @@ public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Null
buffer.writeBoolean(value.damageOnHurt());
}
};
public static final Type<Equippable> TYPE1_21_5 = new Type<>(Equippable.class) {
@Override
public Equippable read(final ByteBuf buffer) {
final int equipmentSlot = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final String model = Types.OPTIONAL_STRING.read(buffer);
final String cameraOverlay = Types.OPTIONAL_STRING.read(buffer);
final HolderSet allowedEntities = Types.OPTIONAL_HOLDER_SET.read(buffer);
final boolean dispensable = buffer.readBoolean();
final boolean swappable = buffer.readBoolean();
final boolean damageOnHurt = buffer.readBoolean();
final boolean equipOnInteract = buffer.readBoolean();
return new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract);
}
public Equippable rewrite(final Int2IntFunction soundIdRewriter) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriter);
return soundEvent == this.soundEvent ? this : new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
@Override
public void write(final ByteBuf buffer, final Equippable value) {
Types.VAR_INT.writePrimitive(buffer, value.equipmentSlot());
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.OPTIONAL_STRING.write(buffer, value.model());
Types.OPTIONAL_STRING.write(buffer, value.cameraOverlay());
Types.OPTIONAL_HOLDER_SET.write(buffer, value.allowedEntities());
buffer.writeBoolean(value.dispensable());
buffer.writeBoolean(value.swappable());
buffer.writeBoolean(value.damageOnHurt());
buffer.writeBoolean(value.equipOnInteract());
}
};
public static final Type<Equippable> TYPE1_21_6 = new Type<>(Equippable.class) {
@Override
public Equippable read(final ByteBuf buffer) {
final int equipmentSlot = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final String model = Types.OPTIONAL_STRING.read(buffer);
final String cameraOverlay = Types.OPTIONAL_STRING.read(buffer);
final HolderSet allowedEntities = Types.OPTIONAL_HOLDER_SET.read(buffer);
final boolean dispensable = buffer.readBoolean();
final boolean swappable = buffer.readBoolean();
final boolean damageOnHurt = buffer.readBoolean();
final boolean equipOnInteract = buffer.readBoolean();
final boolean canBeSheared = buffer.readBoolean();
final Holder<SoundEvent> shearingSound = Types.SOUND_EVENT.read(buffer);
return new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract, canBeSheared, shearingSound);
}
@Override
public void write(final ByteBuf buffer, final Equippable value) {
Types.VAR_INT.writePrimitive(buffer, value.equipmentSlot());
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.OPTIONAL_STRING.write(buffer, value.model());
Types.OPTIONAL_STRING.write(buffer, value.cameraOverlay());
Types.OPTIONAL_HOLDER_SET.write(buffer, value.allowedEntities());
buffer.writeBoolean(value.dispensable());
buffer.writeBoolean(value.swappable());
buffer.writeBoolean(value.damageOnHurt());
buffer.writeBoolean(value.equipOnInteract());
buffer.writeBoolean(value.canBeSheared());
Types.SOUND_EVENT.write(buffer, value.shearingSound());
}
};
@Override
public Equippable rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> shearingSound = this.shearingSound.updateId(Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent && shearingSound == this.shearingSound ? this : new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract, canBeSheared, shearingSound);
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -74,6 +75,13 @@ public abstract class Filterable<T> {
optionalElementType.write(buffer, value.filtered());
}
@Override
public void write(final Ops ops, final F value) {
ops.writeMap(map -> map
.write("raw", elementType, value.raw())
.writeOptional("filtered", elementType, value.filtered()));
}
protected abstract F create(T raw, T filtered);
}
}
@@ -23,12 +23,16 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class FilterableComponent extends Filterable<Tag> {
public final class FilterableComponent extends Filterable<Tag> implements Copyable, Rewritable {
public static final Type<FilterableComponent> TYPE = new FilterableType<>(Types.TAG, Types.OPTIONAL_TAG, FilterableComponent.class) {
@Override
@@ -41,4 +45,21 @@ public final class FilterableComponent extends Filterable<Tag> {
public FilterableComponent(final Tag raw, @Nullable final Tag filtered) {
super(raw, filtered);
}
@Override
public FilterableComponent rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (protocol.getComponentRewriter() == null) {
return this;
}
final FilterableComponent copy = copy();
protocol.getComponentRewriter().processTag(connection, copy.raw());
protocol.getComponentRewriter().processTag(connection, copy.filtered());
return copy;
}
@Override
public FilterableComponent copy() {
return new FilterableComponent(raw().copy(), filtered() != null ? filtered().copy() : null);
}
}
@@ -22,12 +22,18 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.ArrayUtil;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boolean hasTrail, boolean hasTwinkle) {
public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boolean hasTrail,
boolean hasTwinkle) implements Copyable {
public static final String[] SHAPES = {"small_ball", "large_ball", "star", "creeper", "burst"};
public static final Type<FireworkExplosion> TYPE = new Type<>(FireworkExplosion.class) {
@Override
public FireworkExplosion read(final ByteBuf buffer) {
@@ -47,7 +53,21 @@ public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boole
buffer.writeBoolean(value.hasTrail);
buffer.writeBoolean(value.hasTwinkle);
}
@Override
public void write(final Ops ops, final FireworkExplosion value) {
ops.writeMap(map -> map
.write("shape", Types.STRING, SHAPES[value.shape])
.writeOptional("colors", new ArrayType<>(Types.INT), ArrayUtil.boxedArray(value.colors), new Integer[0])
.writeOptional("fade_colors", new ArrayType<>(Types.INT), ArrayUtil.boxedArray(value.fadeColors), new Integer[0])
.writeOptional("has_trail", Types.BOOLEAN, value.hasTrail, false)
.writeOptional("has_twinkle", Types.BOOLEAN, value.hasTwinkle, false));
}
};
public static final Type<FireworkExplosion[]> ARRAY_TYPE = new ArrayType<>(TYPE);
@Override
public FireworkExplosion copy() {
return new FireworkExplosion(shape, Copyable.copy(colors), Copyable.copy(fadeColors), hasTrail, hasTwinkle);
}
}
@@ -22,11 +22,13 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record Fireworks(int flightDuration, FireworkExplosion[] explosions) {
public record Fireworks(int flightDuration, FireworkExplosion[] explosions) implements Copyable {
public static final Type<Fireworks> TYPE = new Type<>(Fireworks.class) {
@Override
@@ -41,6 +43,17 @@ public record Fireworks(int flightDuration, FireworkExplosion[] explosions) {
Types.VAR_INT.writePrimitive(buffer, value.flightDuration);
FireworkExplosion.ARRAY_TYPE.write(buffer, value.explosions);
}
@Override
public void write(final Ops ops, final Fireworks value) {
ops.writeMap(map -> map
.writeOptional("flight_duration", Types.UNSIGNED_BYTE, (short) value.flightDuration, (short) 0)
.writeOptional("explosions", FireworkExplosion.ARRAY_TYPE, value.explosions, new FireworkExplosion[0]));
}
};
@Override
public Fireworks copy() {
return new Fireworks(flightDuration, Copyable.copy(explosions));
}
}
@@ -26,12 +26,13 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record FoodProperties1_20_5(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
@Nullable Item usingConvertsTo, FoodEffect[] possibleEffects) {
@Nullable Item usingConvertsTo, FoodEffect[] possibleEffects) implements Copyable {
public static final Type<FoodProperties1_20_5> TYPE1_20_5 = new Type<>(FoodProperties1_20_5.class) {
@Override
@@ -60,7 +61,7 @@ public record FoodProperties1_20_5(int nutrition, float saturationModifier, bool
final float saturationModifier = buffer.readFloat();
final boolean canAlwaysEat = buffer.readBoolean();
final float eatSeconds = buffer.readFloat();
final Item usingConvertsTo = Types1_21.OPTIONAL_ITEM.read(buffer);
final Item usingConvertsTo = VersionedTypes.V1_21.optionalItem.read(buffer);
final FoodEffect[] possibleEffects = FoodEffect.ARRAY_TYPE.read(buffer);
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo, possibleEffects);
}
@@ -71,11 +72,16 @@ public record FoodProperties1_20_5(int nutrition, float saturationModifier, bool
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
buffer.writeFloat(value.eatSeconds);
Types1_21.OPTIONAL_ITEM.write(buffer, value.usingConvertsTo);
VersionedTypes.V1_21.optionalItem.write(buffer, value.usingConvertsTo);
FoodEffect.ARRAY_TYPE.write(buffer, value.possibleEffects);
}
};
@Override
public FoodProperties1_20_5 copy() {
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo == null ? null : usingConvertsTo.copy(), Copyable.copy(possibleEffects));
}
public record FoodEffect(PotionEffect effect, float probability) {
public static final Type<FoodEffect> TYPE = new Type<>(FoodEffect.class) {
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
@@ -43,5 +44,13 @@ public record FoodProperties1_21_2(int nutrition, float saturationModifier, bool
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
}
@Override
public void write(final Ops ops, final FoodProperties1_21_2 value) {
ops.writeMap(map -> map
.write("nutrition", Types.VAR_INT, value.nutrition)
.write("saturation", Types.FLOAT, value.saturationModifier)
.writeOptional("can_always_eat", Types.BOOLEAN, value.canAlwaysEat, false));
}
};
}
@@ -22,14 +22,16 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, float range) {
public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, float range) implements Rewritable {
public static final HolderType<Instrument1_20_5> TYPE = new HolderType<>() {
@Override
@@ -48,8 +50,9 @@ public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, f
}
};
public Instrument1_20_5 rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
@Override
public Instrument1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new Instrument1_20_5(soundEvent, useDuration, range);
}
}
@@ -23,14 +23,19 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range, Tag description) {
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range,
Tag description) implements Copyable, Rewritable {
public static final HolderType<Instrument1_21_2> TYPE = new HolderType<>() {
@Override
@@ -50,9 +55,16 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
Types.TAG.write(buffer, value.description());
}
};
public static final EitherHolderType<Instrument1_21_2> EITHER_HOLDER_TYPE = new EitherHolderType<>(TYPE);
public Instrument1_21_2 rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
@Override
public Instrument1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, description);
}
@Override
public Instrument1_21_2 copy() {
return new Instrument1_21_2(soundEvent, useDuration, range, description.copy());
}
}
@@ -23,56 +23,72 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Either;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record JukeboxPlayable(Either<Holder<JukeboxSong>, String> song, boolean showInTooltip) {
public record JukeboxPlayable(EitherHolder<JukeboxSong> song, boolean showInTooltip) implements Rewritable {
public JukeboxPlayable(final Holder<JukeboxSong> song, final boolean showInTooltip) {
this(Either.left(song), showInTooltip);
this(EitherHolder.of(song), showInTooltip);
}
public JukeboxPlayable(final String resourceKey, final boolean showInTooltip) {
this(Either.right(resourceKey), showInTooltip);
this(EitherHolder.of(resourceKey), showInTooltip);
}
public static final Type<JukeboxPlayable> TYPE = new Type<>(JukeboxPlayable.class) {
public static final Type<JukeboxPlayable> TYPE1_21 = new Type<>(JukeboxPlayable.class) {
@Override
public JukeboxPlayable read(final ByteBuf buffer) {
final Either<Holder<JukeboxSong>, String> position = Type.readEither(buffer, JukeboxSong.TYPE, Types.STRING);
final EitherHolder<JukeboxSong> position = EitherHolderType.read(buffer, JukeboxSong.TYPE);
final boolean showInTooltip = buffer.readBoolean();
return new JukeboxPlayable(position, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final JukeboxPlayable value) {
Type.writeEither(buffer, value.song, JukeboxSong.TYPE, Types.STRING);
EitherHolderType.write(buffer, value.song, JukeboxSong.TYPE);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<JukeboxPlayable> TYPE1_21_5 = new Type<>(JukeboxPlayable.class) {
@Override
public JukeboxPlayable read(final ByteBuf buffer) {
final EitherHolder<JukeboxSong> position = EitherHolderType.read(buffer, JukeboxSong.TYPE);
return new JukeboxPlayable(position, true);
}
public JukeboxPlayable rewrite(final Int2IntFunction soundIdRewriteFunction) {
if (song.isRight()) {
@Override
public void write(final ByteBuf buffer, final JukeboxPlayable value) {
EitherHolderType.write(buffer, value.song, JukeboxSong.TYPE);
}
};
@Override
public JukeboxPlayable rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (this.song.hasKey()) {
return this;
}
final Holder<JukeboxSong> songHolder = this.song.left();
final Holder<JukeboxSong> songHolder = this.song.holder();
if (songHolder.hasId()) {
return this;
}
final JukeboxSong rewrittenSong = songHolder.value().rewrite(soundIdRewriteFunction);
final JukeboxSong rewrittenSong = songHolder.value().rewrite(connection, protocol, clientbound);
return rewrittenSong == songHolder.value() ? this : new JukeboxPlayable(Holder.of(rewrittenSong), showInTooltip);
}
public record JukeboxSong(Holder<SoundEvent> soundEvent, Tag description,
float lengthInSeconds, int comparatorOutput) {
float lengthInSeconds, int comparatorOutput) implements Rewritable {
public static final HolderType<JukeboxSong> TYPE = new HolderType<>() {
@Override
@@ -93,8 +109,9 @@ public record JukeboxPlayable(Either<Holder<JukeboxSong>, String> song, boolean
}
};
public JukeboxSong rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
@Override
public JukeboxSong rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new JukeboxSong(soundEvent, description, lengthInSeconds, comparatorOutput);
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.GlobalBlockPosition;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
@@ -43,6 +44,12 @@ public record LodestoneTracker(@Nullable GlobalBlockPosition position, boolean t
Types.OPTIONAL_GLOBAL_POSITION.write(buffer, value.position);
buffer.writeBoolean(value.tracked);
}
};
@Override
public void write(final Ops ops, final LodestoneTracker value) {
ops.writeMap(map -> map
.writeOptional("target", Types.GLOBAL_POSITION, value.position)
.writeOptional("tracked", Types.BOOLEAN, value.tracked, true));
}
};
}
@@ -22,12 +22,15 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public final class PotDecorations {
public final class PotDecorations implements Copyable, Rewritable {
public static final Type<PotDecorations> TYPE = new Type<>(PotDecorations.class) {
@Override
@@ -75,11 +78,17 @@ public final class PotDecorations {
return index < 0 || index >= itemIds.length ? -1 : itemIds[index];
}
public PotDecorations rewrite(final Int2IntFunction idRewriteFunction) {
@Override
public PotDecorations rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final int[] newItems = new int[itemIds.length];
for (int i = 0; i < itemIds.length; i++) {
newItems[i] = idRewriteFunction.applyAsInt(itemIds[i]);
newItems[i] = Rewritable.rewriteItem(protocol, clientbound, itemIds[i]);
}
return new PotDecorations(newItems);
}
@Override
public PotDecorations copy() {
return new PotDecorations(Copyable.copy(itemIds));
}
}
@@ -24,11 +24,12 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record PotionContents(@Nullable Integer potion, @Nullable Integer customColor, PotionEffect[] customEffects,
@Nullable String customName) {
@Nullable String customName) implements Copyable {
public PotionContents(final @Nullable Integer potion, final @Nullable Integer customColor, final PotionEffect[] customEffects) {
this(potion, customColor, customEffects, null);
@@ -85,4 +86,9 @@ public record PotionContents(@Nullable Integer potion, @Nullable Integer customC
Types.OPTIONAL_STRING.write(buffer, value.customName);
}
};
@Override
public PotionContents copy() {
return new PotionContents(potion, customColor, Copyable.copy(customEffects), customName);
}
}
@@ -0,0 +1,59 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ProvidesTrimMaterial(EitherHolder<ArmorTrimMaterial> material) implements Rewritable {
public static final Type<ProvidesTrimMaterial> TYPE = new Type<>(ProvidesTrimMaterial.class) {
@Override
public ProvidesTrimMaterial read(final ByteBuf buffer) {
final EitherHolder<ArmorTrimMaterial> position = EitherHolderType.read(buffer, ArmorTrimMaterial.TYPE1_21_5);
return new ProvidesTrimMaterial(position);
}
@Override
public void write(final ByteBuf buffer, final ProvidesTrimMaterial value) {
EitherHolderType.write(buffer, value.material, ArmorTrimMaterial.TYPE1_21_5);
}
};
@Override
public ProvidesTrimMaterial rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (material.hasKey() || material.holder().hasId()) {
return this;
}
final ArmorTrimMaterial trimMaterial = material.holder().value();
return new ProvidesTrimMaterial(EitherHolder.of(Holder.of(trimMaterial.rewrite(connection, protocol, clientbound))));
}
}
@@ -22,20 +22,27 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int damagePerBlock) {
public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int damagePerBlock,
boolean canDestroyBlocksInCreative) implements Rewritable {
public static final Type<ToolProperties> TYPE = new Type<>(ToolProperties.class) {
public ToolProperties(final ToolRule[] rules, final float defaultMiningSpeed, final int damagePerBlock) {
this(rules, defaultMiningSpeed, damagePerBlock, false);
}
public static final Type<ToolProperties> TYPE1_20_5 = new Type<>(ToolProperties.class) {
@Override
public ToolProperties read(final ByteBuf buffer) {
final ToolRule[] rules = ToolRule.ARRAY_TYPE.read(buffer);
final float defaultMiningSpeed = buffer.readFloat();
final int damagePerBlock = Types.VAR_INT.readPrimitive(buffer);
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock);
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock, true);
}
@Override
@@ -45,12 +52,31 @@ public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int dam
Types.VAR_INT.writePrimitive(buffer, value.damagePerBlock());
}
};
public static final Type<ToolProperties> TYPE1_21_5 = new Type<>(ToolProperties.class) {
@Override
public ToolProperties read(final ByteBuf buffer) {
final ToolRule[] rules = ToolRule.ARRAY_TYPE.read(buffer);
final float defaultMiningSpeed = buffer.readFloat();
final int damagePerBlock = Types.VAR_INT.readPrimitive(buffer);
final boolean canDestroyBlocksInCreative = buffer.readBoolean();
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock, canDestroyBlocksInCreative);
}
public ToolProperties rewrite(final Int2IntFunction blockIdRewriter) {
@Override
public void write(final ByteBuf buffer, final ToolProperties value) {
ToolRule.ARRAY_TYPE.write(buffer, value.rules());
buffer.writeFloat(value.defaultMiningSpeed());
Types.VAR_INT.writePrimitive(buffer, value.damagePerBlock());
buffer.writeBoolean(value.canDestroyBlocksInCreative());
}
};
@Override
public ToolProperties rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final ToolRule[] rules = new ToolRule[this.rules.length];
for (int i = 0; i < rules.length; i++) {
rules[i] = this.rules[i].rewrite(blockIdRewriter);
rules[i] = this.rules[i].rewrite(connection, protocol, clientbound);
}
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock);
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock, canDestroyBlocksInCreative);
}
}
@@ -22,15 +22,18 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record ToolRule(HolderSet blocks, @Nullable Float speed, @Nullable Boolean correctForDrops) {
public record ToolRule(HolderSet blocks, @Nullable Float speed,
@Nullable Boolean correctForDrops) implements Rewritable {
public static final Type<ToolRule> TYPE = new Type<>(ToolRule.class) {
@Override
@@ -50,7 +53,8 @@ public record ToolRule(HolderSet blocks, @Nullable Float speed, @Nullable Boolea
};
public static final Type<ToolRule[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public ToolRule rewrite(final Int2IntFunction blockIdRewriter) {
return blocks.hasIds() ? new ToolRule(blocks.rewrite(blockIdRewriter), speed, correctForDrops) : this;
@Override
public ToolRule rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return blocks.hasIds() ? new ToolRule(blocks.rewrite(Rewritable.blockRewriteFunction(protocol, clientbound)), speed, correctForDrops) : this;
}
}
@@ -0,0 +1,82 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSortedSet;
public record TooltipDisplay(boolean hideTooltip,
IntSortedSet hiddenComponents) implements Rewritable { // Keeping the ids raw makes this less annoying to deal with...
public static final Type<TooltipDisplay> TYPE = new Type<>(TooltipDisplay.class) {
@Override
public TooltipDisplay read(final ByteBuf buffer) {
final boolean hideTooltip = buffer.readBoolean();
final IntSortedSet hiddenComponents = new IntLinkedOpenHashSet();
final int size = Types.VAR_INT.readPrimitive(buffer);
for (int i = 0; i < size; i++) {
hiddenComponents.add(Types.VAR_INT.readPrimitive(buffer));
}
return new TooltipDisplay(hideTooltip, hiddenComponents);
}
@Override
public void write(final ByteBuf buffer, final TooltipDisplay value) {
buffer.writeBoolean(value.hideTooltip());
Types.VAR_INT.writePrimitive(buffer, value.hiddenComponents().size());
for (int hiddenComponent : value.hiddenComponents()) {
Types.VAR_INT.writePrimitive(buffer, hiddenComponent);
}
}
@Override
public void write(final Ops ops, final TooltipDisplay value) {
final Key[] hiddenComponents = value.hiddenComponents.intStream().mapToObj(id -> ops.context().registryAccess().dataComponentType(id)).toArray(Key[]::new);
ops.writeMap(map -> map
.writeOptional("hide_tooltip", Types.BOOLEAN, value.hideTooltip, false)
.writeOptional("hidden_components", Types.RESOURCE_LOCATION_ARRAY, hiddenComponents, new Key[0]));
}
};
@Override
public TooltipDisplay rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (hiddenComponents.isEmpty()) {
return this;
}
final IntSortedSet newHiddenComponents = new IntLinkedOpenHashSet();
for (final int hiddenComponent : hiddenComponents) {
newHiddenComponents.add(Rewritable.rewriteDataComponentType(protocol, clientbound, hiddenComponent));
}
return new TooltipDisplay(hideTooltip, newHiddenComponents);
}
}
Loaded 100 of 369 files, more files were not shown because too many files have changed in this diff. Show more