Compare commits

..
140 Commits
Author SHA1 Message Date
Nassim Jahnke 4d5d5e3e7b Avoid full pipeline iteration in raw packet sends
Closes #5136
2026-11-01 11:21:56 +01:00
RK_01 d8415e6f59 Copy registry data before sending configuration packets (#5134) 2026-10-29 11:31:09 +01:00
Nassim Jahnke eb00c5e0b1 Bump version to 5.12.3-SNAPSHOT 2026-10-29 11:30:37 +01:00
Nassim Jahnke ad24236c6b 5.12.2 Release 2026-10-27 15:59:29 +01:00
Nassim Jahnke ab503f497a Update dependencies 2026-10-27 15:56:10 +01:00
Nassim Jahnke 3afc3ee1e1 Add warning for servers running 1.20.5-1.21.4
Effectively unfixable Vanilla protocol exploits make supporting these versions effectively impossible.
2026-10-27 15:56:10 +01:00
Nassim Jahnke cb55edf220 Don't stringify complex packet values in errors
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-OHZWL7WM.
2026-10-27 15:54:07 +01:00
Nassim Jahnke 9f4803b832 Limit serverbound data nesting depth
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-1V7UVEKT.
2026-10-27 15:54:06 +01:00
Nassim Jahnke 88419cdd71 Use arraycopy for primitive array copies
Discovered by Anthropic's OSS Scanner, as ANT-2026-NH253ZCQ.
2026-10-27 15:33:35 +01:00
Nassim Jahnke 2579ac2153 Apply vanilla limits to more serverbound counts
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-GVS9G86J.
2026-10-27 15:33:35 +01:00
Nassim Jahnke 9d2f9f10e7 Don't cache missing paths for unknown versions
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-JJN86714.
2026-10-27 15:33:35 +01:00
Nassim Jahnke 218fc88313 Limit profile key lengths
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-8Z8EOA8N.
2026-10-27 15:33:35 +01:00
Nassim Jahnke 357cb229bc Mask and randomize 1.21.5 item hash keys
Discovered by Anthropic's OSS Scanner, as vulnerabilities ANT-2026-UGG51ZRR and ANT-2026-Z4170OQA.
2026-10-27 15:33:34 +01:00
Nassim Jahnke d89ea4c7be Release packets sent after the channel closed
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-X0V9ES7R.
2026-10-27 15:33:34 +01:00
Nassim Jahnke be08ce39f6 Don't back up nested items in 1.20.3->1.20.5
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-01EM4SCC.
2026-10-27 15:33:34 +01:00
Nassim Jahnke f71f4722e0 Range check original hash ids
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-AECM0IZO.
2026-10-27 10:30:35 +01:00
Nassim Jahnke 62ea10d662 Only convert container items once
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-0RVR8JDH.
2026-10-27 10:30:35 +01:00
Nassim Jahnke ca49a1b4ad Don't presize large arrays
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-0DCBHFG1.
2026-10-27 10:30:35 +01:00
Nassim Jahnke 746740accf Update map types in some data reading
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-HV60WOZ3.
2026-10-27 10:30:35 +01:00
Nassim Jahnke b90f379538 Deactivate on unknown handshake intent
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-RJ1MXTAQ.
2026-10-27 10:30:35 +01:00
Nassim Jahnke 8b9a78aa02 Avoid exceptions in UUID parsing
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-65KLCX8F.
2026-10-27 10:30:35 +01:00
Nassim Jahnke 3487e8ce5f Add sanity checks for config state switching
Discovered by Anthropic's OSS Scanner, as vulnerability ANT-2026-891675B2.
2026-10-27 08:24:44 +01:00
Florian Reuth 73dc869595 Remap trim item sprites to the items atlas in 1.21.9->1.21.11 (#5122) 2026-10-23 10:48:16 +02:00
Nassim Jahnke 66c064ad7d Update deps, move from minotaur to mod-publish-plugin
Minotaur is barely maintained, and mod-publish-plugin lets us remove the annoying version handling
2026-10-21 13:36:23 +02:00
Nassim Jahnke 8d56c71974 Handle hidden_components in show item hovers
Fixes #5128
2026-10-19 20:31:20 +02:00
Nassim Jahnke 28d16ec7d3 Init lastWarning correctly 2026-10-19 20:31:14 +02:00
Florian Reuth fc4b13f0a1 Fix up checks in 1.12.2->1.13 wall connection handling (#5124) 2026-10-19 14:02:26 +02:00
Nassim Jahnke b712c0055d Add some missing sound rewriting 2026-10-18 22:07:58 +02:00
mfishma 08776de832 [ci skip] Update README (#5118) 2026-10-12 18:40:57 +02:00
Florian Reuth 77b7054629 Remove duplicated items tag in 1.20.3->1.20.5 (#5121) 2026-10-12 18:40:14 +02:00
Nassim Jahnke 63769b3661 Fix continuous block breaking sounds
Fixes #5120
2026-10-11 20:08:24 +02:00
mfishma 12d75daf04 Fix item_name restoration when added_custom_name is present (#5109) 2026-10-11 09:48:29 +02:00
Florian Reuth 413268eb15 Delete empty tag in 1.12.2->1.13 (#5115) 2026-10-11 09:41:02 +02:00
Florian Reuth b27e2a5514 Handle existing entity tag properly in 1.12.2->1.13 (#5114) 2026-10-11 09:40:49 +02:00
Florian Reuth c59dfb4d93 Fix NPE if color is missing in patterns in 1.12.2->1.13 (#5113) 2026-10-11 09:40:31 +02:00
Florian Reuth f66cbd6941 Remove empty tags in 1.8->1.9 (#5112) 2026-10-11 09:40:16 +02:00
mfishma 1574f343f7 Downgrade new 26.3 map decorations to target_x (#5110) 2026-10-11 09:39:41 +02:00
Nassim Jahnke 022fb96f83 Handle visible items in block entities
Fixes #1351
2026-10-09 16:43:07 +02:00
Nassim Jahnke 7cbc751fea Bump version to 5.12.2-SNAPSHOT 2026-10-09 16:42:46 +02:00
Nassim Jahnke 366f08d951 Separate Fabric platform on modrinth
... or it'll fail when specifying versions below 1.14
2026-10-08 16:05:13 +02:00
Nassim Jahnke d628f09334 5.12.1 Release 2026-10-08 15:41:05 +02:00
Nassim JahnkeandWhiteProject1 6fecd58773 Check full type length if possible
Closes #5104

Co-authored-by: WhiteProject1 <Odunyasi167@gmail.com>
2026-10-08 15:38:29 +02:00
冰砚炽andNassim Jahnke da7619c82d Fix custom enchantment value_check predicate is not rewritten for 26.3 clients (#5101)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-10-08 15:12:20 +02:00
Nassim Jahnke b83268efa0 Update deps 2026-10-08 11:02:33 +02:00
Florian Reuth 309c3e57c1 Remove map number tag again in 1.16.4->1.17 (#5099) 2026-10-04 08:55:53 +02:00
Florian Reuth 34a445efcd Copy mutable item before updating in 1.20.3->1.20.5 (#5102) 2026-10-04 08:54:12 +02:00
Florian Reuth 3a949d70eb Don't error on invalid filtered pages in 1.20.2->1.20.3 (#5098) 2026-10-02 14:55:26 +02:00
Rocco 99bfa389b4 Fix backwards conversion of new 1.20.5 trim patterns (#5078) 2026-10-01 19:07:09 +02:00
Florian Reuth 327d4739f5 Fix HIDE_ADDITIONAL_TOOLTIP disappearing in 1.21.4->1.21.5 (#5092) 2026-10-01 18:43:08 +02:00
Florian Reuth 3a7a8e06a8 Backup & restore map color in 26.2->26.3 (#5096) 2026-10-01 15:06:47 +02:00
Florian Reuth 85db19200f Upgrade empty swing animation as well in 26.2->26.3 (#5097) 2026-10-01 15:03:49 +02:00
Florian Reuth 226609b864 Don't lose bypassed_by tag key in 1.21.11->26.1 (#5095) 2026-09-30 20:56:50 +02:00
Florian Reuth 7049f7eaf1 Fix bees not spawning after creative mode in 1.21.7->1.21.9 (#5094) 2026-09-30 20:55:49 +02:00
Florian Reuth a062d0905b Don't use random unique id for attribute conversion in 1.20.5->1.21 (#5093) 2026-09-30 08:43:07 +02:00
Florian Reuth 7ac58c104b Fix Consumable animation hashing between 1.21.5 and 1.21.11 (#5087) 2026-09-29 18:37:42 +02:00
Florian Reuth 7a6e838eb1 Inline damage type for 1.21.11 (#5090) 2026-09-29 18:37:24 +02:00
Florian Reuth 57bc53346c Fix sulfur_cube_content network type (#5091) 2026-09-29 16:03:05 +02:00
terbin 3df7c76c8c Add statistic mappings for 1.16.2->1.17 (#5089) 2026-09-29 14:46:34 +02:00
Florian Reuth 3f35005051 Fix default-count item template hashing (#5088) 2026-09-29 14:17:24 +02:00
Florian Reuth f9d21e073b Fix conditional hashing of a bunch of item data components (#5082) 2026-09-29 14:12:08 +02:00
Florian Reuth e813796d9a Handle remaining components in registry data (#5077) 2026-09-28 19:31:54 +02:00
Florian Reuth 271b6e7ff7 Fix splash potion sounds not playing in 26.2->26.3 (#5076) 2026-09-28 19:30:57 +02:00
LeonTG 7bf4a30075 Fix ender dragon having the wrong dragon phase in 1.8->1.9 (#5070) 2026-09-28 08:55:09 +02:00
PolangandFlorian Reuth 414e978829 Skip removal markers in 1.20.5+ item cost type (#5073)
Co-authored-by: Florian Reuth <git@florianreuth.de>
2026-09-28 08:45:15 +02:00
Nassim Jahnke 637a81e569 Handle dripstone particles dimension attribute registry data
Fixes #5074
2026-09-27 14:21:22 +02:00
Florian Reuth b4023127f6 Force set health back >0 in 1.19.1->1.19.3 (#5061) 2026-09-20 14:54:56 +02:00
Nassim Jahnke 46a61058dd Add missing tags across protocols, reduce stored tags size 2026-09-20 13:06:35 +02:00
Nassim Jahnke 66b90a5b2a Add missing tag for newly placed solid blocks letting through rain
Fixes #5060
2026-09-20 11:59:58 +02:00
Florian Reuth 8f03d6bcef Cancel axe stripping for pre 1.13, shovel dirth paths for pre 1.9 (#5057) 2026-09-20 09:44:19 +02:00
Florian Reuth e1809674fd Send brewing recipes for vanilla servers not syncing the inventory in 26.2->26.3 (#5056) 2026-09-19 19:50:12 +02:00
Pantera 4d8b0d1f54 Add missing 26.3 block tags for client predictions 2026-09-19 15:16:57 +02:00
Rocco d1a0c58f5f Restore 26.2 interpolation steps for 26.2->26.3 (#5052) 2026-09-19 12:55:02 +02:00
Dainsleif 724460d2e7 Skip repeated end credits on 1.21+ clients (#5055) 2026-09-19 12:37:59 +02:00
chico ferreira f2e3f53486 Send original client version in Velocity player details (#5043) 2026-09-19 12:20:59 +02:00
Nassim Jahnke 7190e365e4 Bump version to 5.12.1-SNAPSHOT 2026-09-19 12:20:06 +02:00
Nassim Jahnke 50aa9fa3ad 5.12.0 Release 2026-09-18 16:04:35 +02:00
Nassim Jahnke 7497103bac Null check block state Name
Shouldn't be valid, but ?
2026-09-18 16:00:13 +02:00
Nassim Jahnke ff83e2eb6e Fix brewing stand brewing time and fuel display 2026-09-18 16:00:13 +02:00
Nassim JahnkeandCamden Cove 2a75917ef5 Always create mapped chunk type
Types are cached now and need to be created in case global palette bits count changed

Co-authored-by: Camden Cove <me@camdencove.com>
2026-09-18 16:00:13 +02:00
Nassim Jahnke f634879d64 Handle ambient_particles for block state format changes 2026-09-18 16:00:13 +02:00
Nassim Jahnke e6222b38ef Replace new map decoration types when downgrading items 2026-09-18 16:00:13 +02:00
Nassim Jahnke 745a41322f Remove snapshot bit 2026-09-18 16:00:12 +02:00
Nassim Jahnke 72c679acc6 Fix expected move after teleport
Also changes the ViaCodecHandler to a MessageToMessageCodec, as otherwise sync encodes aren't properly processed due to buffering
2026-09-18 16:00:12 +02:00
Florian Reuth 5996340a33 Handle block_state_property registry changes
Fixes joining an Paper 1.8 server with 26.3

Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth a2c1841e25 Fix consume effects hashing key in 1.21.2+
Not related to the 26.3 update but easier than having to deal with merge conflicts after the public release.

Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth 3483d652e8 Update shared registrations to 26.3 changes
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth da29a96844 Replace mask type in player_chat
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth 735a4cacb1 Fix trim plaette id<->asset name conversion
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth d236db51e0 Fix resolvable primitive types write
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth 44167439dd Handle new type in player_action
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Nassim Jahnke 67b7ae4cac Strip namespace in 26.3->26.2 trim data 2026-09-18 16:00:11 +02:00
Florian Reuth cef5abdc73 Handle worldgen/block_state_provider going forward
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth ad7f53c3cd Fix states updating in block state provider
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth e5554c7a8e Handle decorated_pot block entity data
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Florian Reuth cbe42132be Fix consume effect conversion
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Florian Reuth 8023d8237b Remove compostable on item downgrade
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Florian Reuth 0611b95183 Fix pot decorations network type
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Nassim Jahnke d647f169e6 26.3-rc-2 2026-09-18 16:00:10 +02:00
Nassim Jahnke c44b94f96a Fix swing animation handling 2026-09-18 16:00:10 +02:00
Nassim Jahnke 29be35be1c 26.3-rc-1 2026-09-18 16:00:10 +02:00
Nassim Jahnke 9d2c429624 26.3-pre-3 2026-09-18 16:00:10 +02:00
Nassim Jahnke d2ab957ceb Update and restore trim material 2026-09-18 16:00:09 +02:00
Nassim Jahnke 4bbae432b4 26.3-pre-2 2026-09-18 16:00:09 +02:00
Nassim Jahnke bfc2713102 26.3-pre-1 2026-09-18 16:00:09 +02:00
Nassim Jahnke 155863a4c4 26.3-snapshot-10 2026-09-18 16:00:09 +02:00
Nassim Jahnke 8fc649fba9 26.3-snapshot-9 2026-09-18 16:00:09 +02:00
Nassim Jahnke 7edc17759f 26.3-snapshot-8 2026-09-18 16:00:08 +02:00
Nassim Jahnke b607f96988 26.3-snapshot-7 2026-09-18 16:00:08 +02:00
Nassim Jahnke f6b2f6b3ad 26.3-snapshot-6 2026-09-18 16:00:08 +02:00
Nassim Jahnke a7186fb162 26.3-snapshot-5 2026-09-18 16:00:08 +02:00
Nassim Jahnke d2e636bc6f 26.3-snapshot-4 2026-09-18 16:00:08 +02:00
Nassim Jahnke 9cbb829853 Fix movement tick offset 2026-09-18 16:00:07 +02:00
Nassim Jahnke f04f0a07a8 26.3-snapshot-3 2026-09-18 16:00:07 +02:00
Nassim Jahnke 7cf85e38c5 Fix DEBUG_SUBSCRIPTION_REQUEST and GAME_TEST_HIGHLIGHT_POS packet names 2026-09-18 16:00:07 +02:00
Nassim Jahnke 55f449ee74 Implement BlockTransformData rewrite
See code comments
2026-09-18 16:00:07 +02:00
Nassim Jahnke 460214efe2 26.3-snapshot-2 2026-09-18 16:00:07 +02:00
Nassim Jahnke e5cf0fc6c5 26.3-snapshot-1 2026-09-18 15:59:58 +02:00
Nassim Jahnke d2eed62794 Fix 1.9 identifiers file 2026-09-18 08:51:56 +02:00
Beanes 9946d3e9f6 Add 1.9 identifiers (#4976) 2026-09-16 18:08:00 +02:00
EvModder 5f98cba45b Preserve legacy world clocks (#5040) 2026-09-04 20:54:17 +02:00
LeonTG 15a7d8c853 Remove removed stats in 1.11->1.11.1 (#5037) 2026-08-30 17:19:12 +02:00
Beanes 2645d83eb7 Improve hide-scoreboard-numbers to only work for sidebar (#5034) 2026-08-29 14:34:20 +02:00
Nassim Jahnke c23ec2c26f [ci skip] Build script updates 2026-08-23 15:10:06 +02:00
Emir 42380596ee [ci skip] Use instanceof check in ConfigSection#getSerializedComponent (#5025) 2026-08-23 15:09:55 +02:00
Nassim Jahnke 03e0f231ea Fix compilation 2026-08-19 20:38:46 +02:00
Nassim Jahnke eed3de9e3d Move index to AbstractProtocol directly 2026-08-19 20:35:14 +02:00
Nassim Jahnke feb08a31a3 Skip base protocols in hasher protocol loop 2026-08-19 20:10:14 +02:00
Nassim Jahnke e8bbb5da5b Update ViaNBT 2026-08-14 16:03:56 +02:00
Nassim Jahnke 034390dd24 Update deps 2026-08-12 21:50:16 +02:00
Nassim Jahnke 89f80172b1 Move a bunch of protocol storables to direct array lookups
Also has the benefit of making them thread-safe
2026-08-05 16:57:54 +02:00
Nassim Jahnke 5f93e73b8a Create NbtOps
Useful for backup tags in VB
2026-08-05 16:09:13 +02:00
Nassim Jahnke c124b309e0 Ignore invalid legacy show_item in 1.11->1.12
Closes #5014
2026-07-30 09:17:59 +02:00
Nassim Jahnke 122b81dd33 Add shears breaking speed block tags in 26.1->26.2
Fixes #5010
2026-07-23 17:46:09 +02:00
Nassim Jahnke a2896b64fa Fix 1.21.11->26.1 damage_resistant rewriting
Fixes #5008
2026-07-23 16:13:03 +02:00
Nassim Jahnke 2d78597a59 Handle nested identifiers in item hover events
Actually rewrite the important ones (i.e. relevant to tooltips) and remove the others.
2026-07-23 15:23:33 +02:00
Nassim Jahnke 432918645e Fix boat rotation unpacking in 1.21->1.21.2 2026-07-18 19:24:44 +02:00
RiceChen_andNassim Jahnke c20c29fa3a Sort stonecutter recipes by output registry key (#5006)
Fixes #4242

Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-07-15 16:58:08 +02:00
Nassim Jahnke ab85b0e0f0 Build script cleanup
This also moves Fabric and Sponge resource files into the universal dir; we do not publish platform specific jars and this otherwise only leads to a more complicated project setup
2026-07-15 13:12:58 +02:00
Nassim Jahnke 3a5d9541c8 Use netty Buf I/O streams on Java 24+
The JDK had already gotten similar (but much better still) allocation and performance improvements to read and writeUtf methods
2026-07-14 12:39:49 +02:00
Nassim Jahnke 356a5e25f4 Bump version to 5.11.1-SNAPSHOT 2026-07-14 12:05:55 +02:00
312 changed files with 7141 additions and 1279 deletions

No files matched your search

+3 -2
View File
@@ -1,4 +1,5 @@
version: 2
# Disabled for the time being, being done manually instead
updates:
- package-ecosystem: "github-actions"
cooldown:
@@ -6,11 +7,11 @@ updates:
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
open-pull-requests-limit: 0
- package-ecosystem: "gradle"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
open-pull-requests-limit: 0
+4 -4
View File
@@ -11,16 +11,16 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v5.5.0
uses: actions/setup-java@v6.1.0
with:
distribution: 'temurin'
java-version: 17
@@ -30,7 +30,7 @@ jobs:
- name: Upload Artifacts to GitHub
# Only upload on the preview repository as there is no CI job for it.
if: ${{ github.repository == 'ViaVersion/ViaVersionDev' && github.ref_name == 'preview' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: Artifacts
path: build/libs/
+4 -4
View File
@@ -16,16 +16,16 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v5.5.0
uses: actions/setup-java@v6.1.0
with:
distribution: 'temurin'
java-version: 17
@@ -40,5 +40,5 @@ jobs:
- name: Publish to Modrinth
env:
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
run: ./gradlew modrinth --stacktrace
run: ./gradlew publishMods --stacktrace
continue-on-error: true
+2
View File
@@ -37,3 +37,5 @@ bin/
run/
AGENTS.override.md
.claude/
!.claude/CLAUDE.md
+13 -8
View File
@@ -14,18 +14,23 @@ or as [a standalone proxy](https://github.com/ViaVersion/ViaProxy) to join from
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\*
projects.**
Note that ViaVersion will be able to **run best on either Paper servers or
through [ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus?tab=readme-ov-file#viafabricplus)** due to having
direct access to client/server state and more extensive API.
**Note:** While ViaVersion works reliably across all listed platforms, it has the highest performance and state accuracy on **Paper** servers and through **[ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus)** on clients, since both offer more extensive APIs and direct access to client/server state.
Supported Versions:
### Supported Versions
![Table (https://ci.viaversion.com/userContent/images/T.png)](https://ci.viaversion.com/userContent/images/T.png)
| Players joining with… | Install |
| :--- | :--- |
| **Newer** versions than the server | ViaVersion |
| **Older** versions than the server, down to 1.9 | ViaVersion + [ViaBackwards](https://github.com/ViaVersion/ViaBackwards) |
| **1.7.x – 1.8.x** | ViaVersion + [ViaBackwards](https://github.com/ViaVersion/ViaBackwards) + [ViaRewind](https://github.com/ViaVersion/ViaRewind) |
**User Docs:** https://docs.viaversion.com
If you're stuck, try [this tool](https://viaversion.com/setup) to work out what plugins you need.
**User Docs:** [docs.viaversion.com](https://docs.viaversion.com)
Snapshot Support
----------
Snapshot support
--------
**ViaVersion will only be released a few days *after* a Minecraft update** unless the protocol changes of the update
were trivial. If you want early-access, usually days or even weeks before the final release, you can subscribe to
either:
@@ -500,6 +500,13 @@ public interface ViaVersionConfig extends Config {
*/
boolean handleInvalidItemCount();
/**
* Backs up the original data of nested items (e.g. in containers or bundles) for 1.20.5+ clients on 1.20.4 and older servers.
*
* @return true if enabled
*/
boolean backupNestedItems();
/**
* Tries to cancel block break/place sounds sent by 1.8 servers to 1.9+ clients to prevent them from playing twice
*
@@ -508,7 +515,7 @@ public interface ViaVersionConfig extends Config {
boolean cancelBlockSounds();
/**
* Hides scoreboard numbers for 1.20.3+ clients on older server versions.
* Hides sidebar scoreboard numbers for 1.20.3+ clients on older server versions.
*
* @return true if enabled
*/
@@ -0,0 +1,45 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.connection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
/**
* Holds protocol-specific data. Protocols may extend the data wrapper to hold extra data.
*/
public interface ProtocolStorables {
EntityTracker entityTracker();
void setEntityTracker(EntityTracker tracker);
ClientWorld clientWorld();
void setClientWorld(ClientWorld clientWorld);
ItemHasher itemHasher();
void setItemHasher(ItemHasher itemHasher);
}
@@ -22,6 +22,8 @@
*/
package com.viaversion.viaversion.api.connection;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
@@ -36,18 +38,18 @@ import io.netty.channel.ChannelFuture;
import io.netty.handler.codec.CodecException;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface UserConnection {
/**
* Get an object from the storage.
* Get an object from the storage. Useful where protocol instances aren't readily available.
*
* @param objectClass The class of the object to get
* @param <T> The type of the class you want to get.
* @return The requested object
* @see #storables(Protocol)
*/
@Nullable <T extends StorableObject> T get(Class<T> objectClass);
@@ -69,27 +71,56 @@ public interface UserConnection {
@Nullable <T extends StorableObject> T remove(Class<T> objectClass);
/**
* Put an object into the stored objects based on class.
* Put an object into the stored objects based on class. Useful where protocol instances aren't readily available.
*
* @param object The object to store.
* @see #storables(Protocol)
*/
void put(StorableObject object);
/**
* Holds protocol-specific data. Where protocol instances aren't readily available, use {@link #put(StorableObject)}.
*
* @param protocol protocol
* @param <T> protocol-specific storables type
* @return protocol storables
* @throws IllegalArgumentException if the protocol does not have a valid return value for {@link Protocol#index()}
*/
<T extends ProtocolStorables> T storables(Protocol<?, ?, ?, ?> protocol);
/**
* Holds protocol-specific data. Prefer using {@link #storables(Protocol)} where possible.
*
* @param protocolClass protocol class
* @param <T> protocol-specific storables type
* @return protocol storables
* @throws IllegalArgumentException if the protocol does not have a valid return value for {@link Protocol#index()}
* @see #storables(Protocol)
*/
default <T extends ProtocolStorables> T storables(final Class<? extends Protocol> protocolClass) {
return storables(Via.getManager().getProtocolManager().getProtocol(protocolClass));
}
/**
* Returns a collection of entity trackers currently registered.
*
* @return collection of entity trackers currently registered
*/
@Deprecated(forRemoval = true)
Collection<EntityTracker> getEntityTrackers();
@Deprecated(forRemoval = true)
@Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass);
/**
* Returns the entity tracker by the given protocol class if present.
*
* @param protocolClass protocol class
* @param <T> entity tracker type
* @param protocol protocol
* @param <T> entity tracker type
* @return entity tracker if present
* @see com.viaversion.viaversion.api.rewriter.EntityRewriter#tracker(UserConnection)
*/
@Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass);
@Nullable <T extends EntityTracker> T getEntityTracker(Protocol<?, ?, ?, ?> protocol);
/**
* Adds an entity tracker to the user connection.
@@ -97,34 +128,43 @@ public interface UserConnection {
*
* @param protocolClass protocol class
* @param tracker entity tracker
* @deprecated use {@link #storables(Protocol)}
*/
@Deprecated(forRemoval = true)
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
/**
* Returns the item hasher by the given class if present.
*
* @param protocol protocol
* @param <T> item hasher type
* @return item hasher if present
*/
@Nullable <T extends ItemHasher> T getItemHasher(Protocol<?, ?, ?, ?> protocol);
/**
* Adds an item hasher to the user connection.
*
* @param protocolClass protocol class
* @param itemHasher item hasher
* @deprecated use {@link #storables(Protocol)}
*/
@Deprecated(forRemoval = true)
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
*/
@Deprecated(forRemoval = true)
@Nullable <T extends ItemHasher> T getItemHasher(Class<? extends Protocol> protocolClass);
/**
* Returns the client world by the given protocol class if present.
* Returns the client world by the given class if present.
*
* @param protocolClass protocol class
* @param <T> client world type
* @return client world if present
* @deprecated use {@link #storables(Protocol)}
*/
@Nullable
@Deprecated(forRemoval = true)
<T extends ClientWorld> T getClientWorld(Class<? extends Protocol> protocolClass);
/**
@@ -134,6 +174,7 @@ public interface UserConnection {
* @param protocolClass protocol class
* @param clientWorld client world
*/
@Deprecated(forRemoval = true)
void addClientWorld(Class<? extends Protocol> protocolClass, ClientWorld clientWorld);
/**
@@ -26,6 +26,8 @@ import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.function.IntConsumer;
@@ -49,6 +51,12 @@ public final class IdRanges {
return ids;
}
public static IntList decodeAsList(final ByteArrayTag rangesTag) {
final IntList ids = new IntArrayList();
forEachId(rangesTag, ids::add);
return ids;
}
public static void forEachId(final ByteArrayTag rangesTag, final IntConsumer consumer) {
final ByteBuf buf = Unpooled.wrappedBuffer(rangesTag.getValue());
int prevEnd = 0;
@@ -191,6 +191,10 @@ public interface MappingData {
*/
@Nullable IntSet changedBlocks();
default boolean hasBlockChanged(final int blockId) {
return changedBlocks() != null && changedBlocks().contains(blockId);
}
@Nullable Set<String> changedEnvironmentAttributes();
/**
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.ListTag;
@@ -198,8 +199,14 @@ public class MappingDataBase implements MappingData {
final List<TagData> tagsList = new ArrayList<>(tags.size());
for (final Map.Entry<String, Tag> entry : tag.entrySet()) {
final IntArrayTag entries = (IntArrayTag) entry.getValue();
tagsList.add(new TagData(entry.getKey(), entries.getValue()));
final int[] entries;
if (entry.getValue() instanceof final ByteArrayTag rangesTag) {
entries = IdRanges.decodeAsList(rangesTag).toIntArray();
} else {
// Old format / if the values need to be sorted
entries = ((IntArrayTag) entry.getValue()).getValue();
}
tagsList.add(new TagData(entry.getKey(), entries));
}
this.tags.put(type, tagsList);
@@ -79,8 +79,8 @@ public record PaintingVariant(int width, int height, String assetId, @Nullable T
.write("width", Types.INT, value.width())
.write("height", Types.INT, value.height())
.write("asset_id", Types.IDENTIFIER, Key.of(value.assetId()))
.writeOptional("title", Types.TRUSTED_TAG, value.title())
.writeOptional("author", Types.TRUSTED_TAG, value.author()));
.writeOptional("title", Types.TEXT_COMPONENT_TAG, value.title())
.writeOptional("author", Types.TEXT_COMPONENT_TAG, value.author()));
}
@Override
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.util.EitherImpl;
public final class ResolvableFloat extends EitherImpl<Float, String> {
private ResolvableFloat(final Float left, final String right) {
super(left, right);
}
public static ResolvableFloat of(final String value) {
return new ResolvableFloat(null, value);
}
public static ResolvableFloat of(final Float value) {
return new ResolvableFloat(value, null);
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.util.EitherImpl;
public final class ResolvableInt extends EitherImpl<Integer, String> {
private ResolvableInt(final Integer left, final String right) {
super(left, right);
}
public static ResolvableInt of(final String value) {
return new ResolvableInt(null, value);
}
public static ResolvableInt of(final Integer value) {
return new ResolvableInt(value, null);
}
}
@@ -39,4 +39,11 @@ public record SoundEvent(String identifier, @Nullable Float fixedRange) {
}
return holder.updateId(soundRewriteFunction, () -> UNKNOWN);
}
public static @Nullable Holder<SoundEvent> rewriteOptionalHolder(@Nullable final Holder<SoundEvent> holder, final Int2IntFunction soundRewriteFunction) {
if (holder == null) {
return null;
}
return holder.updateId(soundRewriteFunction, () -> null);
}
}
@@ -110,7 +110,7 @@ public final class DataPaletteImpl implements DataPalette {
* Stores palette indexes from a compact long array, replacing all current values.
* The data is kept packed unless written to; reads extract bits the slow way, since almost all work will use replaceIds or will only have a few reads.
* <p>
* Only valid for local palettes (bitsPerValue <= 8).
* Only valid for local palettes (bitsPerValue &lt;= 8).
*
* @param data compact long array
* @param bitsPerValue bits per value
@@ -38,6 +38,8 @@ public interface CodecContext {
UserConnection connection();
Protocol<?, ?, ?, ?> protocol();
interface RegistryAccess {
UserConnection connection();
@@ -58,7 +58,9 @@ public interface Ops {
void writeMap(Consumer<MapSerializer> consumer);
<V> void write(final Type<V> type, final V value);
default <V> void write(final Type<V> type, final V value) {
type.write(this, value);
}
interface ListSerializer {
@@ -30,15 +30,15 @@ import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.RegistryKey;
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
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_11;
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.Item;
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.ArmorTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrim1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrim26_3;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrimMaterial1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrimMaterial26_3;
import com.viaversion.viaversion.api.minecraft.item.data.AttackRange;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
@@ -47,11 +47,14 @@ import com.viaversion.viaversion.api.minecraft.item.data.Bee;
import com.viaversion.viaversion.api.minecraft.item.data.BlockEntityData;
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.BreakSound;
import com.viaversion.viaversion.api.minecraft.item.data.BrewingFuel;
import com.viaversion.viaversion.api.minecraft.item.data.Compostable;
import com.viaversion.viaversion.api.minecraft.item.data.consumable.Consumable1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.CookingFuel;
import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant26_1;
import com.viaversion.viaversion.api.minecraft.item.data.DamageType;
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
import com.viaversion.viaversion.api.minecraft.item.data.DebugStickState;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
@@ -72,12 +75,14 @@ import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable.Jukebox
import com.viaversion.viaversion.api.minecraft.item.data.KineticWeapon;
import com.viaversion.viaversion.api.minecraft.item.data.LockCode;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.MobVisibility;
import com.viaversion.viaversion.api.minecraft.item.data.PiercingWeapon;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesBannerPatterns;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ProvidesTrimMaterial1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.Repairable;
import com.viaversion.viaversion.api.minecraft.item.data.SignText;
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
import com.viaversion.viaversion.api.minecraft.item.data.SwingAnimation;
import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
@@ -86,6 +91,7 @@ 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.UseEffects;
import com.viaversion.viaversion.api.minecraft.item.data.VillagerFood;
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;
@@ -118,7 +124,7 @@ public record StructuredDataKey<T>(String identifier, Type<T> 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.TEXT_COMPONENT_TAG);
public static final StructuredDataKey<Float> MINIMUM_ATTACK_CHARGE = new StructuredDataKey<>("minimum_attack_charge", Types.FLOAT);
public static final StructuredDataKey<DamageType> DAMAGE_TYPE1_21_11 = new StructuredDataKey<>("damage_type", DamageType.TYPE1_21_11);
public static final StructuredDataKey<Either<Integer, String>> DAMAGE_TYPE1_21_11 = new StructuredDataKey<>("damage_type", new SynchronizedRegistryEitherType(RegistryKey.of("damage_type")));
public static final StructuredDataKey<Integer> DAMAGE_TYPE26_1 = new StructuredDataKey<>("damage_type", new SynchronizedRegistryValueType(RegistryKey.of("damage_type")));
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TEXT_COMPONENT_TAG);
public static final StructuredDataKey<ItemModel> ITEM_MODEL = new StructuredDataKey<>("item_model", ItemModel.TYPE);
@@ -145,7 +151,10 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_20_5 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_20_5);
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<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE1_21_2);
// 1.21.5-1.21.9 only, animation id 5 was still named spear
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_5 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE1_21_5);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE26_3 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE26_3);
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<DamageResistant1_21_2> DAMAGE_RESISTANT1_21_2 = new StructuredDataKey<>("damage_resistant", DamageResistant1_21_2.TYPE);
@@ -161,13 +170,18 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Repairable> REPAIRABLE = new StructuredDataKey<>("repairable", Repairable.TYPE);
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
public static final StructuredDataKey<Key> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.IDENTIFIER);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION1_21_2 = new StructuredDataKey<>("death_protection", DeathProtection.TYPE1_21_2);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION26_3 = new StructuredDataKey<>("death_protection", DeathProtection.TYPE26_3);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS1_21_5 = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE1_21_5);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS26_1 = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE26_1);
public static final StructuredDataKey<PiercingWeapon> PIERCING_WEAPON = new StructuredDataKey<>("piercing_weapon", PiercingWeapon.TYPE);
public static final StructuredDataKey<KineticWeapon> KINETIC_WEAPON = new StructuredDataKey<>("kinetic_weapon", KineticWeapon.TYPE);
public static final StructuredDataKey<SwingAnimation> SWING_ANIMATION = new StructuredDataKey<>("swing_animation", SwingAnimation.TYPE);
public static final StructuredDataKey<SwingAnimation> ATTACK_ANIMATION = new StructuredDataKey<>("attack_animation", SwingAnimation.TYPE);
public static final StructuredDataKey<SwingAnimation> INTERACT_ANIMATION = new StructuredDataKey<>("interact_animation", SwingAnimation.TYPE);
public static final StructuredDataKey<Integer> ADDITIONAL_TRADE_COST = new StructuredDataKey<>("additional_trade_cost", Types.VAR_INT);
public static final StructuredDataKey<Integer> BLOCK_TRANSFORMER = new StructuredDataKey<>("block_transformer", new SynchronizedRegistryValueType(RegistryKey.of("block_transformer")));
public static final StructuredDataKey<VillagerFood> VILLAGER_FOOD = new StructuredDataKey<>("villager_food", VillagerFood.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<Integer> DYE = new StructuredDataKey<>("dye", EnumTypes.DYE_COLOR);
@@ -183,10 +197,11 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<SuspiciousStewEffect[]> SUSPICIOUS_STEW_EFFECTS = new StructuredDataKey<>("suspicious_stew_effects", SuspiciousStewEffect.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<ArmorTrim1_20_5> TRIM1_20_5 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_20_5);
public static final StructuredDataKey<ArmorTrim1_20_5> TRIM1_21_2 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_21_2);
public static final StructuredDataKey<ArmorTrim1_20_5> TRIM1_21_4 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_21_4);
public static final StructuredDataKey<ArmorTrim1_20_5> TRIM1_21_5 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_21_5);
public static final StructuredDataKey<ArmorTrim26_3> TRIM26_3 = new StructuredDataKey<>("trim", ArmorTrim26_3.TYPE);
public static final StructuredDataKey<DebugStickState> DEBUG_STICK_STATE = new StructuredDataKey<>("debug_stick_state", DebugStickState.TYPE);
public static final StructuredDataKey<CompoundTag> ENTITY_DATA1_20_5 = new StructuredDataKey<>("entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<EntityData> ENTITY_DATA1_21_9 = new StructuredDataKey<>("entity_data", EntityData.TYPE);
@@ -194,11 +209,13 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<CompoundTag> BLOCK_ENTITY_DATA1_20_5 = new StructuredDataKey<>("block_entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<BlockEntityData> BLOCK_ENTITY_DATA1_21_9 = new StructuredDataKey<>("block_entity_data", BlockEntityData.TYPE);
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<Holder<Instrument1_21_2>> INSTRUMENT1_21_2 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE1_21_2);
public static final StructuredDataKey<EitherHolder<Instrument1_21_2>> INSTRUMENT1_21_5 = new StructuredDataKey<>("instrument", Instrument1_21_2.EITHER_HOLDER_TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT26_1 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
public static final StructuredDataKey<ProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL1_21_5 = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial.TYPE);
public static final StructuredDataKey<Holder<ArmorTrimMaterial>> PROVIDES_TRIM_MATERIAL26_1 = new StructuredDataKey<>("provides_trim_material", ArmorTrimMaterial.TYPE1_21_5);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT26_1 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE1_21_2);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT26_3 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE26_3);
public static final StructuredDataKey<ProvidesTrimMaterial1_20_5> PROVIDES_TRIM_MATERIAL1_21_5 = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial1_20_5.TYPE);
public static final StructuredDataKey<Holder<ArmorTrimMaterial1_20_5>> PROVIDES_TRIM_MATERIAL26_1 = new StructuredDataKey<>("provides_trim_material", ArmorTrimMaterial1_20_5.TYPE1_21_5);
public static final StructuredDataKey<Holder<ArmorTrimMaterial26_3>> PROVIDES_TRIM_MATERIAL26_3 = new StructuredDataKey<>("provides_trim_material", ArmorTrimMaterial26_3.TYPE);
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
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);
@@ -214,14 +231,24 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Key> NOTE_BLOCK_SOUND = new StructuredDataKey<>("note_block_sound", Types.IDENTIFIER);
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", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
public static final StructuredDataKey<PotDecorations1_20_5> POT_DECORATIONS1_20_5 = new StructuredDataKey<>("pot_decorations", PotDecorations1_20_5.TYPE);
// 26.3+ pot decorations are in their own key classes
public static final StructuredDataKey<BlockStateProperties> BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE);
public static final StructuredDataKey<Bee[]> BEES1_20_5 = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE1_20_5);
public static final StructuredDataKey<Bee[]> BEES1_21_9 = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE1_21_9);
public static final StructuredDataKey<Tag> LOCK1_20_5 = new StructuredDataKey<>("lock", Types.TAG);
public static final StructuredDataKey<LockCode> LOCK1_21_2 = new StructuredDataKey<>("lock", LockCode.TYPE);
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<BreakSound> BREAK_SOUND = new StructuredDataKey<>("break_sound", BreakSound.TYPE);
public static final StructuredDataKey<Compostable> COMPOSTABLE = new StructuredDataKey<>("compostable", Compostable.TYPE);
public static final StructuredDataKey<CookingFuel> COOKING_FUEL = new StructuredDataKey<>("cooking_fuel", CookingFuel.TYPE);
public static final StructuredDataKey<BrewingFuel> BREWING_FUEL = new StructuredDataKey<>("brewing_fuel", BrewingFuel.TYPE);
public static final StructuredDataKey<MobVisibility> MOB_VISIBILITY = new StructuredDataKey<>("mob_visibility", MobVisibility.TYPE);
public static final StructuredDataKey<Integer> PROVIDES_POTTERY_PATTERN = new StructuredDataKey<>("provides_pottery_pattern", new SynchronizedRegistryValueType(RegistryKey.of("decorated_pot_pattern")));
public static final StructuredDataKey<SignText> SIGN_TEXT_FRONT = new StructuredDataKey<>("sign_text_front", SignText.TYPE);
public static final StructuredDataKey<SignText> SIGN_TEXT_BACK = new StructuredDataKey<>("sign_text_back", SignText.TYPE);
public static final StructuredDataKey<Unit> WAXED = new StructuredDataKey<>("waxed", Types.EMPTY);
public static final StructuredDataKey<Integer> CUSHION_COLOR = new StructuredDataKey<>("cushion/color", EnumTypes.DYE_COLOR);
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", new SynchronizedRegistryValueType(RegistryKey.of("wolf_variant")));
@@ -33,7 +33,8 @@ public class StructuredDataKeys1_20_5 extends VersionedStructuredDataKeys {
public final StructuredDataKey<Item[]> bundleContents;
public StructuredDataKeys1_20_5(final VersionedTypesHolder types) {
this.container = add("container", types.itemArray());
// Also includes later vanilla limits
this.container = add("container", types.itemArray().withMaxLength(256));
this.chargedProjectiles = add("charged_projectiles", types.itemArray().withMaxLength(1024));
this.bundleContents = add("bundle_contents", types.itemArray().withMaxLength(1024));
}
@@ -32,6 +32,6 @@ public class StructuredDataKeys26_2 extends StructuredDataKeys1_21_11 {
public StructuredDataKeys26_2(final VersionedTypesHolder types) {
super(types);
this.sulfurCubeContent = add("sulfur_cube_content", types.item());
this.sulfurCubeContent = add("sulfur_cube_content", types.itemTemplate());
}
}
@@ -0,0 +1,37 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.PotDecorations26_3;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys26_3 extends StructuredDataKeys26_2 {
public final StructuredDataKey<PotDecorations26_3> potDecorations;
public StructuredDataKeys26_3(final VersionedTypesHolder types) {
super(types);
this.potDecorations = add("pot_decorations", new PotDecorations26_3.PotDecorationsType(types.optionalItemTemplate()));
}
}
@@ -0,0 +1,336 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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 EntityTypes26_3 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),
CUSHION(ENTITY),
// 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),
POPLAR_BOAT(ABSTRACT_BOAT),
POPLAR_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
// Living entities as a larger subclass
LIVING_ENTITY(ENTITY, null),
ARMOR_STAND(LIVING_ENTITY),
// Players
AVATAR(LIVING_ENTITY, null),
MANNEQUIN(AVATAR),
PLAYER(AVATAR),
// Mobs as a larger subclass
MOB(LIVING_ENTITY, null),
ENDER_DRAGON(MOB),
// 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),
COPPER_GOLEM(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_CUBE_MOB(ABSTRACT_AGEABLE, null),
SLIME(ABSTRACT_CUBE_MOB),
MAGMA_CUBE(ABSTRACT_CUBE_MOB),
SULFUR_CUBE(ABSTRACT_CUBE_MOB),
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),
OCELOT(ABSTRACT_ANIMAL),
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
COW(ABSTRACT_COW),
MOOSHROOM(ABSTRACT_COW),
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
CAT(TAMABLE_ANIMAL),
WOLF(TAMABLE_ANIMAL),
PARROT(TAMABLE_ANIMAL),
ABSTRACT_NAUTILUS(TAMABLE_ANIMAL, null),
NAUTILUS(ABSTRACT_NAUTILUS),
ZOMBIE_NAUTILUS(ABSTRACT_NAUTILUS),
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
HORSE(ABSTRACT_HORSE),
SKELETON_HORSE(ABSTRACT_HORSE),
ZOMBIE_HORSE(ABSTRACT_HORSE),
CAMEL(ABSTRACT_HORSE),
CAMEL_HUSK(CAMEL),
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),
PARCHED(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;
EntityTypes26_3(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes26_3(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,83 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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 EntityDataTypes26_3 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.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_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 particleType;
public final EntityDataType particlesType;
public final EntityDataType villagerDataType = add(18, Types.VILLAGER_DATA);
public final EntityDataType optionalVarIntType = add(19, Types.OPTIONAL_VAR_INT);
public final EntityDataType poseType = add(20, Types.VAR_INT);
public final EntityDataType catVariantType = add(21, Types.VAR_INT);
public final EntityDataType catSoundVariant = add(22, Types.VAR_INT);
public final EntityDataType cowVariantType = add(23, Types.VAR_INT);
public final EntityDataType cowSoundVariant = add(24, Types.VAR_INT);
public final EntityDataType wolfVariantType = add(25, Types.VAR_INT);
public final EntityDataType wolfSoundVariantType = add(26, Types.VAR_INT);
public final EntityDataType frogVariantType = add(27, Types.VAR_INT);
public final EntityDataType pigVariantType = add(28, Types.VAR_INT);
public final EntityDataType pigSoundVariant = add(29, Types.VAR_INT);
public final EntityDataType chickenVariantType = add(30, Types.VAR_INT);
public final EntityDataType chickenSoundVariant = add(31, Types.VAR_INT);
public final EntityDataType zombieNautilusVariantType = add(32, Types.VAR_INT);
public final EntityDataType optionalGlobalPosition = add(33, Types.OPTIONAL_GLOBAL_POSITION);
public final EntityDataType paintingVariantType = add(34, PaintingVariant.TYPE1_21_2);
public final EntityDataType snifferState = add(35, Types.VAR_INT);
public final EntityDataType armadilloState = add(36, Types.VAR_INT);
public final EntityDataType copperGolemState = add(37, Types.VAR_INT);
public final EntityDataType weatheringCopperState = add(38, Types.VAR_INT);
public final EntityDataType vector3FType = add(39, Types.VECTOR3F);
public final EntityDataType quaternionType = add(40, Types.QUATERNION);
public final EntityDataType mannequinProfileType = add(41, Types.RESOLVABLE_PROFILE);
public final EntityDataType humanoidArmType = add(42, Types.VAR_INT);
public final EntityDataType dyeColorType = add(43, Types.VAR_INT);
public EntityDataTypes26_3(final VersionedTypesHolder types) {
super(44);
this.itemType = add(7, types.item());
this.particleType = add(16, types.particle());
this.particlesType = add(17, types.particles());
}
}
@@ -27,7 +27,7 @@ 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.HashMap;
import java.util.Map;
public record BlockStateProperties(Map<String, String> properties) implements Copyable {
@@ -36,7 +36,7 @@ public record BlockStateProperties(Map<String, String> properties) implements Co
@Override
public BlockStateProperties read(final ByteBuf buffer) {
final int size = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> properties = new Object2ObjectOpenHashMap<>();
final Map<String, String> properties = new HashMap<>();
for (int i = 0; i < size; i++) {
properties.put(Types.STRING.read(buffer), Types.STRING.read(buffer));
}
@@ -64,6 +64,6 @@ public record BlockStateProperties(Map<String, String> properties) implements Co
@Override
public BlockStateProperties copy() {
return new BlockStateProperties(new Object2ObjectOpenHashMap<>(properties));
return new BlockStateProperties(new HashMap<>(properties));
}
}
@@ -130,8 +130,8 @@ public record BlocksAttacks(
@Override
public BlocksAttacks rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> blockSound = SoundEvent.rewriteHolder(this.blockSound, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> disableSound = SoundEvent.rewriteHolder(this.disableSound, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> blockSound = SoundEvent.rewriteOptionalHolder(this.blockSound, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> disableSound = SoundEvent.rewriteOptionalHolder(this.disableSound, Rewritable.soundRewriteFunction(protocol, clientbound));
return new BlocksAttacks(this.blockDelaySeconds, this.disableCooldownScale, this.damageReductions, this.itemDamage, this.bypassedBy, blockSound, disableSound);
}
@@ -0,0 +1,43 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Rewritable;
public record BreakSound(Holder<SoundEvent> sound) implements Rewritable {
public static final Type<BreakSound> TYPE = TransformingType.of(Types.SOUND_EVENT, BreakSound.class, BreakSound::new, BreakSound::sound);
@Override
public BreakSound rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> sound = SoundEvent.rewriteHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
return this.sound == sound ? this : new BreakSound(sound);
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.ResolvableFloat;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
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 BrewingFuel(ResolvableInt uses, ResolvableFloat speedMultiplier) {
public static final Type<BrewingFuel> TYPE = new Type<>(BrewingFuel.class) {
@Override
public BrewingFuel read(final ByteBuf buffer) {
final ResolvableInt uses = Types.RESOLVABLE_INT.read(buffer);
final ResolvableFloat speedMultiplier = Types.RESOLVABLE_FLOAT.read(buffer);
return new BrewingFuel(uses, speedMultiplier);
}
@Override
public void write(final ByteBuf buffer, final BrewingFuel value) {
Types.RESOLVABLE_INT.write(buffer, value.uses);
Types.RESOLVABLE_FLOAT.write(buffer, value.speedMultiplier);
}
@Override
public void write(final Ops ops, final BrewingFuel value) {
ops.writeMap(map -> map
.write("uses", Types.RESOLVABLE_INT, value.uses)
.write("speed_multiplier", Types.RESOLVABLE_FLOAT, value.speedMultiplier));
}
};
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.ResolvableInt;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
public record Compostable(ResolvableInt layers) {
public static final Type<Compostable> TYPE = new TransformingType<>(Types.RESOLVABLE_INT, Compostable.class, Compostable::new, Compostable::layers) {
@Override
public void write(final Ops ops, final Compostable value) {
ops.writeMap(map -> map.write("layers", Types.RESOLVABLE_INT, value.layers));
}
};
}
@@ -1,200 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.data.MappingData;
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.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.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
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;
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
boolean hasConsumeParticles,
ConsumeEffect<?>[] consumeEffects) implements Copyable, Rewritable {
private static final HolderSetType REMOVE_EFFECTS_TYPE = new HolderSetType() {
@Override
public void write(final Ops ops, final HolderSet value) {
ops.writeMap(map -> map.write("effects", new HolderSetType(EnumTypes.MOB_EFFECT), value));
}
};
private static final Type<Float> TELEPORT_RANDOMLY_TYPE = new Type<>(Float.class) {
@Override
public void write(final ByteBuf buffer, final Float value) {
Types.FLOAT.writePrimitive(buffer, value);
}
@Override
public Float read(final ByteBuf buffer) {
return Types.FLOAT.readPrimitive(buffer);
}
@Override
public void write(final Ops ops, final Float value) {
ops.writeMap(map -> map.write("diameter", Types.FLOAT, 16F));
}
};
private static final HolderType<SoundEvent> PLAY_SOUND_TYPE = new HolderType<>(MappingData.MappingType.SOUND) {
@Override
public SoundEvent readDirect(final ByteBuf buffer) {
return Types.SOUND_EVENT.readDirect(buffer);
}
@Override
public void writeDirect(final ByteBuf buffer, final SoundEvent value) {
Types.SOUND_EVENT.writeDirect(buffer, value);
}
@Override
public void write(final Ops ops, final Holder<SoundEvent> value) {
ops.writeMap(map -> map.write("sound", Types.SOUND_EVENT, value));
}
};
public static final Type<?>[] EFFECT_TYPES = {
ApplyStatusEffects.TYPE,
REMOVE_EFFECTS_TYPE,
Types.EMPTY, // clear all effects
TELEPORT_RANDOMLY_TYPE,
PLAY_SOUND_TYPE
};
public static final Type<Consumable1_21_2> TYPE = new Type<>(Consumable1_21_2.class) {
@Override
public Consumable1_21_2 read(final ByteBuf buffer) {
final float consumeSeconds = buffer.readFloat();
final int animationType = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
final boolean hasConsumeParticles = buffer.readBoolean();
final ConsumeEffect<?>[] consumeEffects = ConsumeEffect.ARRAY_TYPE.read(buffer);
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, consumeEffects);
}
@Override
public void write(final ByteBuf buffer, final Consumable1_21_2 value) {
buffer.writeFloat(value.consumeSeconds);
Types.VAR_INT.writePrimitive(buffer, value.animationType);
Types.SOUND_EVENT.write(buffer, value.sound);
buffer.writeBoolean(value.hasConsumeParticles);
ConsumeEffect.ARRAY_TYPE.write(buffer, value.consumeEffects);
}
@Override
public void write(final Ops ops, final Consumable1_21_2 value) {
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "entity.generic.eat"));
ops.writeMap(map -> map
.writeOptional("consume_seconds", Types.FLOAT, value.consumeSeconds, 1.6F)
.writeOptional("animation", EnumTypes.ITEM_USE_ANIMATION, value.animationType, 1)
.writeOptional("sound", Types.SOUND_EVENT, value.sound, defaultSound)
.writeOptional("has_consume_particles", Types.BOOLEAN, value.hasConsumeParticles, true)
.writeOptional("consume_effects", ConsumeEffect.ARRAY_TYPE, value.consumeEffects, new ConsumeEffect<?>[0]));
}
};
public record ConsumeEffect<T>(int id, Type<T> type, T value) {
public static final Type<ConsumeEffect<?>> TYPE = new Type<>(ConsumeEffect.class) {
@Override
public ConsumeEffect<?> read(final ByteBuf buffer) {
// Oh no...
final int effectType = Types.VAR_INT.readPrimitive(buffer);
final Type<?> type = EFFECT_TYPES[effectType];
final Object value = type.read(buffer);
return ConsumeEffect.of(effectType, type, value);
}
@Override
public void write(final ByteBuf buffer, final ConsumeEffect<?> value) {
Types.VAR_INT.writePrimitive(buffer, value.id);
value.writeValue(buffer);
}
@Override
public void write(final Ops ops, final ConsumeEffect<?> value) {
writeGeneric(ops, value);
}
private <E> void writeGeneric(final Ops ops, final ConsumeEffect<E> value) {
ops.writeMap(map -> map
.write("type", EnumTypes.CONSUME_EFFECT, value.id)
.writeInlinedMap(value.type, value.value));
}
};
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE = new ArrayType<>(TYPE);
static <T> ConsumeEffect<T> of(final int id, final Type<T> type, final Object value) {
//noinspection unchecked
return new ConsumeEffect<>(id, type, (T) value);
}
void writeValue(final ByteBuf buf) {
this.type.write(buf, this.value);
}
}
public record ApplyStatusEffects(PotionEffect[] effects, float probability) {
public static final Type<ApplyStatusEffects> TYPE = new Type<>(ApplyStatusEffects.class) {
@Override
public ApplyStatusEffects read(final ByteBuf buffer) {
final PotionEffect[] effects = PotionEffect.ARRAY_TYPE.read(buffer);
final float probability = buffer.readFloat();
return new ApplyStatusEffects(effects, probability);
}
@Override
public void write(final ByteBuf buffer, final ApplyStatusEffects value) {
PotionEffect.ARRAY_TYPE.write(buffer, value.effects);
buffer.writeFloat(value.probability);
}
@Override
public void write(final Ops ops, final ApplyStatusEffects value) {
ops.writeMap(map -> map
.write("effects", PotionEffect.ARRAY_TYPE, value.effects)
.writeOptional("probability", Types.FLOAT, value.probability, 1F));
}
};
}
@Override
public Consumable1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundHolder = SoundEvent.rewriteHolder(this.sound, 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-2026 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.ResolvableFloat;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
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 CookingFuel(ResolvableInt burnTime, ResolvableFloat speedMultiplier) {
public static final Type<CookingFuel> TYPE = new Type<>(CookingFuel.class) {
@Override
public CookingFuel read(final ByteBuf buffer) {
final ResolvableInt burnTime = Types.RESOLVABLE_INT.read(buffer);
final ResolvableFloat speedMultiplier = Types.RESOLVABLE_FLOAT.read(buffer);
return new CookingFuel(burnTime, speedMultiplier);
}
@Override
public void write(final ByteBuf buffer, final CookingFuel value) {
Types.RESOLVABLE_INT.write(buffer, value.burnTime);
Types.RESOLVABLE_FLOAT.write(buffer, value.speedMultiplier);
}
@Override
public void write(final Ops ops, final CookingFuel value) {
ops.writeMap(map -> map
.write("burn_time", Types.RESOLVABLE_INT, value.burnTime)
.write("speed_multiplier", Types.RESOLVABLE_FLOAT, value.speedMultiplier));
}
};
}
@@ -22,20 +22,35 @@
*/
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.minecraft.item.data.Consumable1_21_2.ConsumeEffect;
import com.viaversion.viaversion.api.minecraft.item.data.consumable.ConsumeEffect;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyable {
public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyable, Rewritable {
public static final Type<DeathProtection> TYPE = new TransformingType<>(ConsumeEffect.ARRAY_TYPE, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
public static final Type<DeathProtection> TYPE1_21_2 = new TransformingType<>(ConsumeEffect.ARRAY_TYPE1_21_2, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
@Override
public void write(final Ops ops, final DeathProtection value) {
ops.writeMap(map -> map.write("death_effects", ConsumeEffect.ARRAY_TYPE, value.deathEffects));
ops.writeMap(map -> map.writeOptional("death_effects", ConsumeEffect.ARRAY_TYPE1_21_2, value.deathEffects, new ConsumeEffect<?>[0]));
}
};
public static final Type<DeathProtection> TYPE26_3 = new TransformingType<>(ConsumeEffect.ARRAY_TYPE26_3, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
@Override
public void write(final Ops ops, final DeathProtection value) {
ops.writeMap(map -> map.writeOptional("death_effects", ConsumeEffect.ARRAY_TYPE26_3, value.deathEffects, new ConsumeEffect<?>[0]));
}
};
@Override
public DeathProtection rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final ConsumeEffect<?>[] deathEffects = ConsumeEffect.rewrite(this.deathEffects, connection, protocol, clientbound);
return deathEffects == this.deathEffects ? this : new DeathProtection(deathEffects);
}
@Override
public DeathProtection copy() {
@@ -38,12 +38,12 @@ public record DebugStickState(CompoundTag tag) implements Rewritable, Copyable {
@Override
public DebugStickState rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
CompoundTag updatedTag = tag;
if (clientbound && protocol.getMappingData() != null && protocol.getMappingData().changedBlocks() != null) {
if (protocol.getMappingData() != null && protocol.getMappingData().changedBlocks() != null) {
updatedTag = tag.copy();
// Anything beyond this isn't worth the disk space/handling
updatedTag.entrySet().removeIf(entry -> {
final int blockId = protocol.getMappingData().getFullBlockMappings().id(entry.getKey());
return protocol.getMappingData().changedBlocks().contains(blockId);
return blockId == -1 || protocol.getMappingData().changedBlocks().contains(blockId);
});
}
return new DebugStickState(updatedTag);
@@ -27,6 +27,7 @@ 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 com.viaversion.viaversion.util.Limit;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
@@ -41,7 +42,7 @@ public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) imple
@Override
public Enchantments read(final ByteBuf buffer) {
final Int2IntMap enchantments = new Int2IntOpenHashMap();
final int size = Types.VAR_INT.readPrimitive(buffer);
final int size = Limit.max(Types.VAR_INT.readPrimitive(buffer), 256);
for (int i = 0; i < size; i++) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final int level = Types.VAR_INT.readPrimitive(buffer);
@@ -65,7 +66,7 @@ public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) imple
@Override
public Enchantments read(final ByteBuf buffer) {
final Int2IntMap enchantments = new Int2IntOpenHashMap();
final int size = Types.VAR_INT.readPrimitive(buffer);
final int size = Limit.max(Types.VAR_INT.readPrimitive(buffer), 256);
for (int i = 0; i < size; i++) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final int level = Types.VAR_INT.readPrimitive(buffer);
@@ -46,7 +46,8 @@ public final class EnumTypes {
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");
public static final EnumType EQUIPMENT_SLOT = new EnumType("mainhand", "feet", "legs", "chest", "head", "offhand", "body", "saddle");
public static final EnumType SWING_ANIMATION = new EnumType("none", "whack", "stab");
public static final EnumType SWING_ANIMATION1_21_11 = new EnumType("none", "whack", "stab");
public static final EnumType ITEM_USE_ANIMATION1_21_5 = new EnumType("none", "eat", "drink", "block", "bow", "spear", "crossbow", "spyglass", "toot_horn", "brush", "bundle");
public static final EnumType ITEM_USE_ANIMATION = new EnumType("none", "eat", "drink", "block", "bow", "trident", "crossbow", "spyglass", "toot_horn", "brush", "bundle", "spear");
// 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"));
@@ -34,7 +34,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
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) {
public static final Type<FilterableComponent> TYPE = new FilterableType<>(Types.TEXT_COMPONENT_TAG, Types.OPTIONAL_TAG, FilterableComponent.class) {
@Override
protected FilterableComponent create(final Tag raw, final Tag filtered) {
return new FilterableComponent(raw, filtered);
@@ -37,9 +37,13 @@ import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range,
Tag description) implements Copyable, Rewritable {
int durabilityDamage, Tag description) implements Copyable, Rewritable {
public static final HolderType<Instrument1_21_2> TYPE = new HolderType<>() {
public Instrument1_21_2(final Holder<SoundEvent> soundEvent, final float useDuration, final float range, final Tag description) {
this(soundEvent, useDuration, range, 0, description);
}
public static final HolderType<Instrument1_21_2> TYPE1_21_2 = new HolderType<>() {
@Override
public Instrument1_21_2 readDirect(final ByteBuf buffer) {
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
@@ -63,7 +67,44 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
.write("sound_event", Types.SOUND_EVENT, value.soundEvent())
.write("use_duration", Types.FLOAT, value.useDuration())
.write("range", Types.FLOAT, value.range())
.write("description", Types.TAG, value.description()));
.write("description", Types.TEXT_COMPONENT_TAG, value.description()));
}
@Override
protected Key identifier(final Ops ops, final int id) {
return ops.context().registryAccess().registryKey("instrument", id);
}
};
public static final EitherHolderType<Instrument1_21_2> EITHER_HOLDER_TYPE = new EitherHolderType<>(TYPE1_21_2);
public static final HolderType<Instrument1_21_2> TYPE26_3 = new HolderType<>() {
@Override
public Instrument1_21_2 readDirect(final ByteBuf buffer) {
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final float useDuration = Types.FLOAT.readPrimitive(buffer);
final float range = Types.FLOAT.readPrimitive(buffer);
final int durabilityDamage = Types.VAR_INT.readPrimitive(buffer);
final Tag description = Types.TAG.read(buffer);
return new Instrument1_21_2(soundEvent, useDuration, range, durabilityDamage, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final Instrument1_21_2 value) {
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.FLOAT.writePrimitive(buffer, value.useDuration());
Types.FLOAT.writePrimitive(buffer, value.range());
Types.VAR_INT.writePrimitive(buffer, value.durabilityDamage());
Types.TAG.write(buffer, value.description());
}
@Override
public void writeDirect(final Ops ops, final Instrument1_21_2 value) {
ops.writeMap(map -> map
.write("sound_event", Types.SOUND_EVENT, value.soundEvent())
.write("use_duration", Types.FLOAT, value.useDuration())
.write("range", Types.FLOAT, value.range())
.writeOptional("durability_damage", Types.VAR_INT, value.durabilityDamage(), 0)
.write("description", Types.TEXT_COMPONENT_TAG, value.description()));
}
@Override
@@ -71,16 +112,15 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
return ops.context().registryAccess().registryKey("instrument", id);
}
};
public static final EitherHolderType<Instrument1_21_2> EITHER_HOLDER_TYPE = new EitherHolderType<>(TYPE);
@Override
public Instrument1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = SoundEvent.rewriteHolder(this.soundEvent, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, description);
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, durabilityDamage, description);
}
@Override
public Instrument1_21_2 copy() {
return new Instrument1_21_2(soundEvent, useDuration, range, description.copy());
return new Instrument1_21_2(soundEvent, useDuration, range, durabilityDamage, description.copy());
}
}
@@ -22,19 +22,22 @@
*/
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.minecraft.codec.Ops;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.OptionalType;
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 org.checkerframework.checker.nullness.qual.Nullable;
public record KineticWeapon(int contactCooldownTicks, int delayTicks, @Nullable Condition dismountConditions,
@Nullable Condition knockbackConditions, @Nullable Condition damageConditions,
float forwardMovement, float damageMultiplier,
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) {
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) implements Rewritable {
public static final Type<KineticWeapon> TYPE = new Type<>(KineticWeapon.class) {
@Override
@@ -80,6 +83,13 @@ public record KineticWeapon(int contactCooldownTicks, int delayTicks, @Nullable
}
};
@Override
public KineticWeapon rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> sound = SoundEvent.rewriteOptionalHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> hitSound = SoundEvent.rewriteOptionalHolder(this.hitSound, Rewritable.soundRewriteFunction(protocol, clientbound));
return sound == this.sound && hitSound == this.hitSound ? this : new KineticWeapon(contactCooldownTicks, delayTicks, dismountConditions, knockbackConditions, damageConditions, forwardMovement, damageMultiplier, sound, hitSound);
}
public record Condition(int maxDurationTicks, float minSpeed, float minRelativeSpeed) {
public static final Type<Condition> TYPE = new Type<>(Condition.class) {
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.data.MappingData;
import com.viaversion.viaversion.api.minecraft.HolderSet;
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.misc.HolderSetType;
import io.netty.buffer.ByteBuf;
public record MobVisibility(HolderSet targetingEntityTypes, float visibility) {
public static final Type<MobVisibility> TYPE = new Type<>(MobVisibility.class) {
@Override
public MobVisibility read(final ByteBuf buffer) {
final HolderSet targetingEntityTypes = Types.HOLDER_SET.read(buffer);
final float visibility = Types.FLOAT.readPrimitive(buffer);
return new MobVisibility(targetingEntityTypes, visibility);
}
@Override
public void write(final ByteBuf buffer, final MobVisibility value) {
Types.HOLDER_SET.write(buffer, value.targetingEntityTypes);
Types.FLOAT.writePrimitive(buffer, value.visibility);
}
@Override
public void write(final Ops ops, final MobVisibility value) {
ops.writeMap(map -> map
.write("targeting_entity_types", new HolderSetType(MappingData.MappingType.ENTITY_TYPE), value.targetingEntityTypes)
.write("visibility", Types.FLOAT, value.visibility));
}
};
}
@@ -22,16 +22,19 @@
*/
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.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.Rewritable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record PiercingWeapon(boolean dealsKnockback, boolean dismounts,
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) {
@Nullable Holder<SoundEvent> sound, @Nullable Holder<SoundEvent> hitSound) implements Rewritable {
public static final Type<PiercingWeapon> TYPE = new Type<>(PiercingWeapon.class) {
@Override
@@ -61,4 +64,11 @@ public record PiercingWeapon(boolean dealsKnockback, boolean dismounts,
);
}
};
@Override
public PiercingWeapon rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> sound = SoundEvent.rewriteOptionalHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> hitSound = SoundEvent.rewriteOptionalHolder(this.hitSound, Rewritable.soundRewriteFunction(protocol, clientbound));
return sound == this.sound && hitSound == this.hitSound ? this : new PiercingWeapon(dealsKnockback, dismounts, sound, hitSound);
}
}
@@ -29,22 +29,25 @@ import com.viaversion.viaversion.api.type.TransformingType;
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 com.viaversion.viaversion.util.Rewritable;
public record PotDecorations(int[] itemIds) implements Copyable, Rewritable {
public record PotDecorations1_20_5(int[] itemIds) implements Copyable, Rewritable {
public static final Type<PotDecorations> TYPE = new TransformingType<>(Types.VAR_INT_ARRAY_PRIMITIVE, PotDecorations.class, PotDecorations::new, PotDecorations::itemIds) {
private static final Key BRICK = Key.ofPath("brick");
public static final Type<PotDecorations1_20_5> TYPE = new TransformingType<>(Types.VAR_INT_ARRAY_PRIMITIVE, PotDecorations1_20_5.class, PotDecorations1_20_5::new, PotDecorations1_20_5::itemIds) {
@Override
public void write(final Ops ops, final PotDecorations value) {
public void write(final Ops ops, final PotDecorations1_20_5 value) {
// Vanilla always encodes all 4 sides, filling missing ones with bricks
ops.writeList(list -> {
for (final int itemId : value.itemIds) {
list.write(Types.IDENTIFIER, ops.context().registryAccess().item(itemId));
for (int i = 0; i < 4; i++) {
list.write(Types.IDENTIFIER, i < value.itemIds.length ? ops.context().registryAccess().item(value.itemIds[i]) : BRICK);
}
});
}
};
public PotDecorations(final int backItem, final int leftItem, final int rightItem, final int frontItem) {
public PotDecorations1_20_5(final int backItem, final int leftItem, final int rightItem, final int frontItem) {
this(new int[]{backItem, leftItem, rightItem, frontItem});
}
@@ -69,16 +72,16 @@ public record PotDecorations(int[] itemIds) implements Copyable, Rewritable {
}
@Override
public PotDecorations rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
public PotDecorations1_20_5 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] = Rewritable.rewriteItem(protocol, clientbound, itemIds[i]);
}
return new PotDecorations(newItems);
return new PotDecorations1_20_5(newItems);
}
@Override
public PotDecorations copy() {
return new PotDecorations(Copyable.copy(itemIds));
public PotDecorations1_20_5 copy() {
return new PotDecorations1_20_5(Copyable.copy(itemIds));
}
}
@@ -0,0 +1,96 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
import static com.viaversion.viaversion.util.Rewritable.rewriteItem;
public record PotDecorations26_3(@Nullable Item back, @Nullable Item left, @Nullable Item right,
@Nullable Item front) implements Copyable, Rewritable {
public static final class PotDecorationsType extends Type<PotDecorations26_3> {
private final Type<Item> itemTemplateType;
public PotDecorationsType(final Type<Item> itemTemplateType) {
super(PotDecorations26_3.class);
this.itemTemplateType = itemTemplateType;
}
@Override
public void write(final ByteBuf buffer, final PotDecorations26_3 value) {
itemTemplateType.write(buffer, value.back());
itemTemplateType.write(buffer, value.left());
itemTemplateType.write(buffer, value.right());
itemTemplateType.write(buffer, value.front());
}
@Override
public PotDecorations26_3 read(final ByteBuf buffer) {
final Item back = itemTemplateType.read(buffer);
final Item left = itemTemplateType.read(buffer);
final Item right = itemTemplateType.read(buffer);
final Item front = itemTemplateType.read(buffer);
return new PotDecorations26_3(back, left, right, front);
}
@Override
public void write(final Ops ops, final PotDecorations26_3 value) {
ops.writeMap(map -> map
.writeOptional("back", itemTemplateType, value.back())
.writeOptional("left", itemTemplateType, value.left())
.writeOptional("right", itemTemplateType, value.right())
.writeOptional("front", itemTemplateType, value.front())
);
}
}
@Override
public PotDecorations26_3 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new PotDecorations26_3(
rewriteItem(connection, protocol, clientbound, back),
rewriteItem(connection, protocol, clientbound, left),
rewriteItem(connection, protocol, clientbound, right),
rewriteItem(connection, protocol, clientbound, front)
);
}
@Override
public PotDecorations26_3 copy() {
return new PotDecorations26_3(
back == null ? null : back.copy(),
left == null ? null : left.copy(),
right == null ? null : right.copy(),
front == null ? null : front.copy()
);
}
}
@@ -40,7 +40,7 @@ public record PotionEffectData(int amplifier, int duration, boolean ambient, boo
final boolean ambient = buffer.readBoolean();
final boolean showParticles = buffer.readBoolean();
final boolean showIcon = buffer.readBoolean();
final PotionEffectData hiddenEffect = OPTIONAL_TYPE.read(buffer);
final PotionEffectData hiddenEffect = OPTIONAL_TYPE.readTrackingDepth(buffer);
return new PotionEffectData(amplifier, duration, ambient, showParticles, showIcon, hiddenEffect);
}
@@ -0,0 +1,61 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.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 io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record SignText(Tag[] messages, Tag @Nullable [] filteredMessages, int color, boolean hasGlowingText) {
public static final Type<SignText> TYPE = new Type<>(SignText.class) {
@Override
public SignText read(final ByteBuf buffer) {
final Tag[] messages = Types.SIGN_TEXT.read(buffer);
final Tag[] filteredMessages = Types.OPTIONAL_SIGN_TEXT.read(buffer);
final int color = Types.VAR_INT.readPrimitive(buffer);
final boolean hasGlowingText = buffer.readBoolean();
return new SignText(messages, filteredMessages, color, hasGlowingText);
}
@Override
public void write(final ByteBuf buffer, final SignText value) {
Types.SIGN_TEXT.write(buffer, value.messages);
Types.OPTIONAL_SIGN_TEXT.write(buffer, value.filteredMessages);
Types.VAR_INT.writePrimitive(buffer, value.color);
Types.BOOLEAN.write(buffer, value.hasGlowingText);
}
@Override
public void write(final Ops ops, final SignText value) {
ops.writeMap(map -> map
.write("messages", Types.TEXT_COMPONENT_TAG_ARRAY, value.messages)
.writeOptional("filtered_messages", Types.TEXT_COMPONENT_TAG_ARRAY, value.filteredMessages)
.write("color", EnumTypes.DYE_COLOR, value.color)
.write("has_glowing_text", Types.BOOLEAN, value.hasGlowingText));
}
};
}
@@ -29,9 +29,17 @@ import io.netty.buffer.ByteBuf;
public record SwingAnimation(int type, int duration) {
private static final int DEFAULT_TYPE = EnumTypes.SWING_ANIMATION.idFromName("whack");
public static final Type<SwingAnimation> TYPE = new SwingAnimationType(EnumTypes.SWING_ANIMATION1_21_11.idFromName("whack"));
private static class SwingAnimationType extends Type<SwingAnimation> {
private final int defaultType;
public SwingAnimationType(final int defaultType) {
super(SwingAnimation.class);
this.defaultType = defaultType;
}
public static final Type<SwingAnimation> TYPE = new Type<>(SwingAnimation.class) {
@Override
public SwingAnimation read(final ByteBuf buffer) {
final int type = Types.VAR_INT.readPrimitive(buffer);
@@ -48,9 +56,8 @@ public record SwingAnimation(int type, int duration) {
@Override
public void write(final Ops ops, final SwingAnimation value) {
ops.writeMap(map -> map
.writeOptional("type", EnumTypes.SWING_ANIMATION, value.type, DEFAULT_TYPE)
.writeOptional("duration", Types.INT, value.duration, 6)
);
.writeOptional("type", EnumTypes.SWING_ANIMATION1_21_11, value.type, this.defaultType)
.writeOptional("duration", Types.INT, value.duration, 6));
}
};
}
}
@@ -28,6 +28,7 @@ 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.Limit;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
@@ -42,7 +43,7 @@ public record TooltipDisplay(boolean hideTooltip,
public TooltipDisplay read(final ByteBuf buffer) {
final boolean hideTooltip = buffer.readBoolean();
final IntSortedSet hiddenComponents = new IntLinkedOpenHashSet();
final int size = Types.VAR_INT.readPrimitive(buffer);
final int size = Limit.max(Types.VAR_INT.readPrimitive(buffer), 256);
for (int i = 0; i < size; i++) {
hiddenComponents.add(Types.VAR_INT.readPrimitive(buffer));
}
@@ -22,18 +22,18 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.EitherType;
import com.viaversion.viaversion.util.Either;
/**
* 1.21.11-only damage type.
*
* @param id registry int or string id
*/
public record DamageType(Either<Integer, String> id) {
public record VillagerFood(int nutrition) {
public static final Type<DamageType> TYPE1_21_11 = TransformingType.of(new EitherType<>(Types.VAR_INT, Types.STRING), DamageType.class, DamageType::new, DamageType::id);
public static final Type<VillagerFood> TYPE = new TransformingType<>(Types.VAR_INT, VillagerFood.class, VillagerFood::new, VillagerFood::nutrition) {
@Override
public void write(final Ops ops, final VillagerFood value) {
ops.writeMap(map -> map.write("nutrition", Types.VAR_INT, value.nutrition));
}
};
}
@@ -0,0 +1,54 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.data.PotionEffect;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record ApplyStatusEffects(PotionEffect[] effects, float probability) {
public static final Type<ApplyStatusEffects> TYPE = new Type<>(ApplyStatusEffects.class) {
@Override
public ApplyStatusEffects read(final ByteBuf buffer) {
final PotionEffect[] effects = PotionEffect.ARRAY_TYPE.read(buffer);
final float probability = buffer.readFloat();
return new ApplyStatusEffects(effects, probability);
}
@Override
public void write(final ByteBuf buffer, final ApplyStatusEffects value) {
PotionEffect.ARRAY_TYPE.write(buffer, value.effects);
buffer.writeFloat(value.probability);
}
@Override
public void write(final Ops ops, final ApplyStatusEffects value) {
ops.writeMap(map -> map
.write("effects", PotionEffect.ARRAY_TYPE, value.effects)
.writeOptional("probability", Types.FLOAT, value.probability, 1F));
}
};
}
@@ -0,0 +1,101 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.data.EnumTypes;
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.EnumType;
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) implements Copyable, Rewritable {
public static final Type<Consumable1_21_2> TYPE1_21_2 = new ConsumableType(ConsumeEffect.ARRAY_TYPE1_21_2, EnumTypes.ITEM_USE_ANIMATION);
public static final Type<Consumable1_21_2> TYPE1_21_5 = new ConsumableType(ConsumeEffect.ARRAY_TYPE1_21_2, EnumTypes.ITEM_USE_ANIMATION1_21_5);
public static final Type<Consumable1_21_2> TYPE26_3 = new ConsumableType(ConsumeEffect.ARRAY_TYPE26_3, EnumTypes.ITEM_USE_ANIMATION);
private static final class ConsumableType extends Type<Consumable1_21_2> {
private final Type<ConsumeEffect<?>[]> consumeEffectType;
private final EnumType animationType;
private ConsumableType(final Type<ConsumeEffect<?>[]> consumeEffectType, final EnumType animationType) {
super(Consumable1_21_2.class);
this.consumeEffectType = consumeEffectType;
this.animationType = animationType;
}
@Override
public Consumable1_21_2 read(final ByteBuf buffer) {
final float consumeSeconds = buffer.readFloat();
final int animationType = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
final boolean hasConsumeParticles = buffer.readBoolean();
final ConsumeEffect<?>[] consumeEffects = consumeEffectType.read(buffer);
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, consumeEffects);
}
@Override
public void write(final ByteBuf buffer, final Consumable1_21_2 value) {
buffer.writeFloat(value.consumeSeconds);
Types.VAR_INT.writePrimitive(buffer, value.animationType);
Types.SOUND_EVENT.write(buffer, value.sound);
buffer.writeBoolean(value.hasConsumeParticles);
consumeEffectType.write(buffer, value.consumeEffects);
}
@Override
public void write(final Ops ops, final Consumable1_21_2 value) {
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "entity.generic.eat"));
ops.writeMap(map -> map
.writeOptional("consume_seconds", Types.FLOAT, value.consumeSeconds, 1.6F)
.writeOptional("animation", animationType, value.animationType, 1)
.writeOptional("sound", Types.SOUND_EVENT, value.sound, defaultSound)
.writeOptional("has_consume_particles", Types.BOOLEAN, value.hasConsumeParticles, true)
.writeOptional("on_consume_effects", consumeEffectType, value.consumeEffects, new ConsumeEffect<?>[0]));
}
}
@Override
public Consumable1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundHolder = SoundEvent.rewriteHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
final ConsumeEffect<?>[] consumeEffects = ConsumeEffect.rewrite(this.consumeEffects, connection, protocol, clientbound);
return soundHolder == this.sound && consumeEffects == this.consumeEffects ? 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,194 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
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.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.data.EnumTypes;
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.api.type.types.misc.HolderSetType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ConsumeEffect<T>(int id, Type<T> type, T value) implements Rewritable {
private static final HolderSetType REMOVE_EFFECTS_TYPE = new HolderSetType() {
@Override
public void write(final Ops ops, final HolderSet value) {
ops.writeMap(map -> map.write("effects", new HolderSetType(EnumTypes.MOB_EFFECT), value));
}
};
public static final Type<Float> TELEPORT_RANDOMLY_TYPE1_21_2 = new Type<>(Float.class) {
@Override
public void write(final ByteBuf buffer, final Float value) {
Types.FLOAT.writePrimitive(buffer, value);
}
@Override
public Float read(final ByteBuf buffer) {
return Types.FLOAT.readPrimitive(buffer);
}
@Override
public void write(final Ops ops, final Float value) {
ops.writeMap(map -> map.writeOptional("diameter", Types.FLOAT, value, 16F));
}
};
public static final Type<TeleportRandomlyConsumeEffect> TELEPORT_RANDOMLY_TYPE26_3 = new Type<>(TeleportRandomlyConsumeEffect.class) {
@Override
public void write(final ByteBuf buffer, final TeleportRandomlyConsumeEffect value) {
Types.FLOAT.writePrimitive(buffer, value.diameter());
Types.BOOLEAN.write(buffer, value.directionalParticles());
}
@Override
public TeleportRandomlyConsumeEffect read(final ByteBuf buffer) {
final float diameter = Types.FLOAT.readPrimitive(buffer);
final boolean directionalParticles = Types.BOOLEAN.read(buffer);
return new TeleportRandomlyConsumeEffect(diameter, directionalParticles);
}
@Override
public void write(final Ops ops, final TeleportRandomlyConsumeEffect value) {
ops.writeMap(map -> map
.writeOptional("diameter", Types.FLOAT, value.diameter(), 16F)
.writeOptional("directional_particles", Types.BOOLEAN, value.directionalParticles(), true)
);
}
};
private static final HolderType<SoundEvent> PLAY_SOUND_TYPE = new HolderType<>(MappingData.MappingType.SOUND) {
@Override
public SoundEvent readDirect(final ByteBuf buffer) {
return Types.SOUND_EVENT.readDirect(buffer);
}
@Override
public void writeDirect(final ByteBuf buffer, final SoundEvent value) {
Types.SOUND_EVENT.writeDirect(buffer, value);
}
@Override
public void write(final Ops ops, final Holder<SoundEvent> value) {
ops.writeMap(map -> map.write("sound", Types.SOUND_EVENT, value));
}
};
public static final Type<?>[] EFFECT_TYPES1_21_2 = {
ApplyStatusEffects.TYPE,
REMOVE_EFFECTS_TYPE,
Types.EMPTY, // clear all effects
TELEPORT_RANDOMLY_TYPE1_21_2,
PLAY_SOUND_TYPE
};
public static final Type<?>[] EFFECT_TYPES26_3 = {
ApplyStatusEffects.TYPE,
REMOVE_EFFECTS_TYPE,
Types.EMPTY, // clear all effects
TELEPORT_RANDOMLY_TYPE26_3,
PLAY_SOUND_TYPE
};
public static final Type<ConsumeEffect<?>> TYPE1_21_2 = new ConsumeEffectType(EFFECT_TYPES1_21_2);
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE1_21_2 = new ArrayType<>(TYPE1_21_2);
public static final Type<ConsumeEffect<?>> TYPE26_3 = new ConsumeEffectType(EFFECT_TYPES26_3);
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE26_3 = new ArrayType<>(TYPE26_3);
static <T> ConsumeEffect<T> of(final int id, final Type<T> type, final Object value) {
//noinspection unchecked
return new ConsumeEffect<>(id, type, (T) value);
}
@Override
public ConsumeEffect<T> rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (this.type != PLAY_SOUND_TYPE) {
return this;
}
//noinspection unchecked
final Holder<SoundEvent> sound = (Holder<SoundEvent>) this.value;
final Holder<SoundEvent> rewrittenSound = SoundEvent.rewriteHolder(sound, Rewritable.soundRewriteFunction(protocol, clientbound));
return rewrittenSound == sound ? this : ConsumeEffect.of(this.id, this.type, rewrittenSound);
}
public static ConsumeEffect<?>[] rewrite(final ConsumeEffect<?>[] effects, final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
ConsumeEffect<?>[] rewrittenEffects = effects;
for (int i = 0; i < effects.length; i++) {
final ConsumeEffect<?> rewrittenEffect = effects[i].rewrite(connection, protocol, clientbound);
if (rewrittenEffect != effects[i]) {
if (rewrittenEffects == effects) {
rewrittenEffects = effects.clone();
}
rewrittenEffects[i] = rewrittenEffect;
}
}
return rewrittenEffects;
}
void writeValue(final ByteBuf buf) {
this.type.write(buf, this.value);
}
private static final class ConsumeEffectType extends Type<ConsumeEffect<?>> {
private final Type<?>[] types;
private ConsumeEffectType(final Type<?>[] types) {
super(ConsumeEffect.class);
this.types = types;
}
@Override
public ConsumeEffect<?> read(final ByteBuf buffer) {
// Oh no...
final int effectType = Types.VAR_INT.readPrimitive(buffer);
final Type<?> type = types[effectType];
final Object value = type.read(buffer);
return ConsumeEffect.of(effectType, type, value);
}
@Override
public void write(final ByteBuf buffer, final ConsumeEffect<?> value) {
Types.VAR_INT.writePrimitive(buffer, value.id);
value.writeValue(buffer);
}
@Override
public void write(final Ops ops, final ConsumeEffect<?> value) {
writeGeneric(ops, value);
}
private <E> void writeGeneric(final Ops ops, final ConsumeEffect<E> value) {
ops.writeMap(map -> map
.write("type", EnumTypes.CONSUME_EFFECT, value.id)
.writeInlinedMap(value.type, value.value));
}
}
}
@@ -0,0 +1,26 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
public record TeleportRandomlyConsumeEffect(float diameter, boolean directionalParticles) {
}
@@ -20,7 +20,7 @@
* 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;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
@@ -30,86 +30,86 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern,
boolean showInTooltip) implements Rewritable {
public record ArmorTrim1_20_5(Holder<ArmorTrimMaterial1_20_5> material, Holder<ArmorTrimPattern> pattern,
boolean showInTooltip) implements Rewritable {
public ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern) {
public ArmorTrim1_20_5(Holder<ArmorTrimMaterial1_20_5> material, Holder<ArmorTrimPattern> pattern) {
this(material, pattern, true);
}
public static final Type<ArmorTrim> TYPE1_20_5 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_20_5 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_20_5.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_20_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_20_5.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_20_5.write(buffer, value.material);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_2 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_21_2 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_2.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_21_2.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_2.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_21_2.write(buffer, value.material);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_4 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_21_4 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_4.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_21_4.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_4.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_21_4.write(buffer, value.material);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_5 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_21_5 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_5.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_21_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_21_5.read(buffer);
return new ArmorTrim(material, pattern);
return new ArmorTrim1_20_5(material, pattern);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_5.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_21_5.write(buffer, value.material);
ArmorTrimPattern.TYPE1_21_5.write(buffer, value.pattern);
}
@Override
public void write(final Ops ops, final ArmorTrim value) {
public void write(final Ops ops, final ArmorTrim1_20_5 value) {
ops.writeMap(map -> map
.write("material", ArmorTrimMaterial.TYPE1_21_5, value.material)
.write("material", ArmorTrimMaterial1_20_5.TYPE1_21_5, value.material)
.write("pattern", ArmorTrimPattern.TYPE1_21_5, value.pattern));
}
};
@Override
public ArmorTrim rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimMaterial> material = this.material;
public ArmorTrim1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimMaterial1_20_5> material = this.material;
if (material.isDirect()) {
material = Holder.of(material.value().rewrite(connection, protocol, clientbound));
}
@@ -118,6 +118,6 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
if (pattern.isDirect()) {
pattern = Holder.of(pattern.value().rewrite(connection, protocol, clientbound));
}
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
}
@@ -0,0 +1,66 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.trim;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
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.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ArmorTrim26_3(Holder<ArmorTrimMaterial26_3> material,
Holder<ArmorTrimPattern> pattern) implements Rewritable {
public static final Type<ArmorTrim26_3> TYPE = new Type<>(ArmorTrim26_3.class) {
@Override
public ArmorTrim26_3 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial26_3> material = ArmorTrimMaterial26_3.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_21_5.read(buffer);
return new ArmorTrim26_3(material, pattern);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim26_3 value) {
ArmorTrimMaterial26_3.TYPE.write(buffer, value.material);
ArmorTrimPattern.TYPE1_21_5.write(buffer, value.pattern);
}
@Override
public void write(final Ops ops, final ArmorTrim26_3 value) {
ops.writeMap(map -> map
.write("material", ArmorTrimMaterial26_3.TYPE, value.material)
.write("pattern", ArmorTrimPattern.TYPE1_21_5, value.pattern));
}
};
@Override
public ArmorTrim26_3 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimPattern> pattern = this.pattern;
if (pattern.isDirect()) {
pattern = Holder.of(pattern.value().rewrite(connection, protocol, clientbound));
}
return new ArmorTrim26_3(material, pattern);
}
}
@@ -20,7 +20,7 @@
* 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;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -32,32 +32,32 @@ import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.util.HashMap;
import java.util.Map;
public record ArmorTrimMaterial(String assetName, int itemId, float itemModelIndex,
Map<String, String> overrideArmorMaterials,
Tag description) implements Copyable, Rewritable {
public record ArmorTrimMaterial1_20_5(String assetName, int itemId, float itemModelIndex,
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) {
public ArmorTrimMaterial1_20_5(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) {
public ArmorTrimMaterial1_20_5(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<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> 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:
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
final Map<String, String> overrideArmorMaterials = new HashMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final int key = Types.VAR_INT.readPrimitive(buffer);
final String value = Types.STRING.read(buffer);
@@ -65,11 +65,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, itemModelIndex, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, item, itemModelIndex, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
buffer.writeFloat(value.itemModelIndex());
@@ -83,15 +83,15 @@ 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<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> TYPE1_21_2 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
final Map<String, String> overrideArmorMaterials = new HashMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
@@ -99,11 +99,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, itemModelIndex, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, item, itemModelIndex, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
buffer.writeFloat(value.itemModelIndex());
@@ -117,14 +117,14 @@ 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<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> TYPE1_21_4 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
final Map<String, String> overrideArmorMaterials = new HashMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
@@ -132,11 +132,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, item, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
@@ -149,13 +149,13 @@ 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<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> TYPE1_21_5 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
final Map<String, String> overrideArmorMaterials = new HashMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
@@ -163,11 +163,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
@@ -180,7 +180,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
@Override
public void writeDirect(final Ops ops, final ArmorTrimMaterial object) {
public void writeDirect(final Ops ops, final ArmorTrimMaterial1_20_5 object) {
ops.writeMap(map -> {
map.write("asset_name", Types.STRING, object.assetName());
if (!object.overrideArmorMaterials.isEmpty()) {
@@ -201,12 +201,12 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
};
@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);
public ArmorTrimMaterial1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new ArmorTrimMaterial1_20_5(assetName, Rewritable.rewriteItem(protocol, clientbound, itemId), itemModelIndex, overrideArmorMaterials, description);
}
@Override
public ArmorTrimMaterial copy() {
return new ArmorTrimMaterial(assetName, itemId, itemModelIndex, new Object2ObjectArrayMap<>(overrideArmorMaterials), description);
public ArmorTrimMaterial1_20_5 copy() {
return new ArmorTrimMaterial1_20_5(assetName, itemId, itemModelIndex, new HashMap<>(overrideArmorMaterials), description);
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.trim;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
public record ArmorTrimMaterial26_3(String paletteId, Tag description) {
public static final HolderType<ArmorTrimMaterial26_3> TYPE = new HolderType<>() {
@Override
public ArmorTrimMaterial26_3 readDirect(final ByteBuf buffer) {
final String paletteId = Types.STRING.read(buffer);
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial26_3(paletteId, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial26_3 value) {
Types.STRING.write(buffer, value.paletteId());
Types.TAG.write(buffer, value.description());
}
@Override
public void writeDirect(final Ops ops, final ArmorTrimMaterial26_3 object) {
ops.writeMap(map -> {
map.write("palette_id", Types.IDENTIFIER, Key.of(object.paletteId()));
map.write("description", Types.TEXT_COMPONENT_TAG, object.description());
});
}
@Override
protected Key identifier(final Ops ops, final int id) {
return ops.context().registryAccess().registryKey("trim_material", id);
}
};
}
@@ -20,7 +20,7 @@
* 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;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -20,7 +20,7 @@
* 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;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
@@ -32,34 +32,34 @@ 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 record ProvidesTrimMaterial1_20_5(EitherHolder<ArmorTrimMaterial1_20_5> material) implements Rewritable {
public static final Type<ProvidesTrimMaterial> TYPE = new Type<>(ProvidesTrimMaterial.class) {
public static final Type<ProvidesTrimMaterial1_20_5> TYPE = new Type<>(ProvidesTrimMaterial1_20_5.class) {
@Override
public ProvidesTrimMaterial read(final ByteBuf buffer) {
final EitherHolder<ArmorTrimMaterial> position = EitherHolderType.read(buffer, ArmorTrimMaterial.TYPE1_21_5);
return new ProvidesTrimMaterial(position);
public ProvidesTrimMaterial1_20_5 read(final ByteBuf buffer) {
final EitherHolder<ArmorTrimMaterial1_20_5> position = EitherHolderType.read(buffer, ArmorTrimMaterial1_20_5.TYPE1_21_5);
return new ProvidesTrimMaterial1_20_5(position);
}
@Override
public void write(final ByteBuf buffer, final ProvidesTrimMaterial value) {
EitherHolderType.write(buffer, value.material, ArmorTrimMaterial.TYPE1_21_5);
public void write(final ByteBuf buffer, final ProvidesTrimMaterial1_20_5 value) {
EitherHolderType.write(buffer, value.material, ArmorTrimMaterial1_20_5.TYPE1_21_5);
}
@Override
public void write(final Ops ops, final ProvidesTrimMaterial value) {
EitherHolderType.write(ops, value.material, ArmorTrimMaterial.TYPE1_21_5);
public void write(final Ops ops, final ProvidesTrimMaterial1_20_5 value) {
EitherHolderType.write(ops, value.material, ArmorTrimMaterial1_20_5.TYPE1_21_5);
}
};
@Override
public ProvidesTrimMaterial rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
public ProvidesTrimMaterial1_20_5 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))));
final ArmorTrimMaterial1_20_5 trimMaterial = material.holder().value();
return new ProvidesTrimMaterial1_20_5(EitherHolder.of(Holder.of(trimMaterial.rewrite(connection, protocol, clientbound))));
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.protocol;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.connection.ProtocolStorables;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
@@ -33,6 +34,7 @@ import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
@@ -58,6 +60,22 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*/
public interface Protocol<CU extends ClientboundPacketType, CM extends ClientboundPacketType, SM extends ServerboundPacketType, SU extends ServerboundPacketType> {
/**
* Returns the server protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the server protocol version
*/
@Nullable ProtocolVersion getServerVersion();
/**
* Returns the client protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the client protocol version for this protocol
*/
@Nullable ProtocolVersion getClientVersion();
default void registerClientbound(State state, ClientboundPacketType packetType, @Nullable PacketHandler handler) {
Preconditions.checkArgument(packetType.state() == state);
registerClientbound(state, packetType.getId(), packetType.getId(), handler, false);
@@ -460,6 +478,15 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
return false;
}
/**
* Returns the index assigned to this protocol during registration.
*
* @return protocol index, or -1 if not yet registered
*/
int index();
ProtocolStorables createStorables();
/**
* Marks this protocol as dependent on another. Before being initialized, it will wait for the dependency's completion.
*
@@ -318,4 +318,12 @@ public interface ProtocolManager {
* @return whether the mappings have been loaded
*/
boolean hasLoadedMappings();
/**
* Returns the number of registered protocols.
* Used to size per-connection protocol data arrays.
*
* @return number of registered protocols
*/
int registeredProtocolCount();
}
@@ -165,7 +165,7 @@ public class PacketTracker {
// Warning system
private long warningPeriodStart = System.nanoTime();
private long lastWarning = Long.MIN_VALUE;
private long lastWarning = warningPeriodStart - SECOND_NANOS;
private int warnings;
public RateTracker(int windowSize) {
@@ -28,5 +28,11 @@ public enum State {
STATUS,
LOGIN,
CONFIGURATION,
PLAY
PLAY;
private static final int STATES_COUNT = values().length;
public static int statesCount() {
return STATES_COUNT;
}
}
@@ -27,7 +27,7 @@ import java.util.Arrays;
import org.checkerframework.checker.nullness.qual.Nullable;
final class PacketArrayMappings implements PacketMappings {
private final PacketMapping[][] packets = new PacketMapping[State.values().length][];
private final PacketMapping[][] packets = new PacketMapping[State.statesCount()][];
@Override
public @Nullable PacketMapping mappedPacket(final State state, final int unmappedId) {
@@ -95,6 +95,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_21_11 = register(774, "1.21.11");
public static final ProtocolVersion v26_1 = register(775, "26.1-26.1.2", new SubVersionRange("26.1", 0, 2));
public static final ProtocolVersion v26_2 = register(776, "26.2");
public static final ProtocolVersion v26_3 = register(777, "26.3");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -87,6 +87,6 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
* @return entity tracker
*/
default <E extends EntityTracker> E tracker(UserConnection connection) {
return connection.getEntityTracker(protocol().getClass());
return connection.getEntityTracker(protocol());
}
}
@@ -36,6 +36,8 @@ public interface RegistryDataRewriter {
void updateDialog(UserConnection connection, CompoundTag tag);
boolean updateBlockStateProvider(CompoundTag tag);
/**
* Sends registries that had additional entries configured, but weren't sent by the server at all
* by the time finish_configuration was sent to the client.
@@ -23,6 +23,8 @@
package com.viaversion.viaversion.api.type;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.util.NestingLimiter;
import io.netty.buffer.ByteBuf;
/**
* Type for buffer reading and writing.
@@ -63,6 +65,22 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T>, Cod
return typeName != null && !typeName.isEmpty() ? typeName : this.getClass().getName();
}
/**
* Reads a value and counts it towards the nesting depth limit of the current thread, to be used by recursive types.
*
* @param buffer buffer to read from
* @return read value
* @see NestingLimiter
*/
public T readTrackingDepth(final ByteBuf buffer) {
NestingLimiter.increment();
try {
return read(buffer);
} finally {
NestingLimiter.decrement();
}
}
@Override
public void write(Ops ops, T value) {
throw new UnsupportedOperationException("Write operation not supported for type: " + getTypeName());
@@ -36,6 +36,8 @@ import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature;
import com.viaversion.viaversion.api.minecraft.ProfileKey;
import com.viaversion.viaversion.api.minecraft.Quaternion;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.ResolvableFloat;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.Vector;
@@ -58,6 +60,7 @@ import com.viaversion.viaversion.api.type.types.ByteType;
import com.viaversion.viaversion.api.type.types.ComponentType;
import com.viaversion.viaversion.api.type.types.DoubleType;
import com.viaversion.viaversion.api.type.types.EmptyType;
import com.viaversion.viaversion.api.type.types.FixedLengthArrayType;
import com.viaversion.viaversion.api.type.types.FloatArrayType;
import com.viaversion.viaversion.api.type.types.FloatType;
import com.viaversion.viaversion.api.type.types.IntArrayType;
@@ -105,6 +108,7 @@ import com.viaversion.viaversion.api.type.types.math.EulerAngleType;
import com.viaversion.viaversion.api.type.types.math.GlobalBlockPositionType;
import com.viaversion.viaversion.api.type.types.math.LowPrecisionVectorType;
import com.viaversion.viaversion.api.type.types.math.QuaternionType;
import com.viaversion.viaversion.api.type.types.math.Vector3dType;
import com.viaversion.viaversion.api.type.types.math.Vector3fType;
import com.viaversion.viaversion.api.type.types.math.VectorType;
import com.viaversion.viaversion.api.type.types.misc.CompoundTagHolderType;
@@ -118,6 +122,8 @@ import com.viaversion.viaversion.api.type.types.misc.NamedCompoundTagType;
import com.viaversion.viaversion.api.type.types.misc.PlayerMessageSignatureType;
import com.viaversion.viaversion.api.type.types.misc.ProfileKeyType;
import com.viaversion.viaversion.api.type.types.misc.ProfilePropertyType;
import com.viaversion.viaversion.api.type.types.misc.ResolvableFloatType;
import com.viaversion.viaversion.api.type.types.misc.ResolvableIntType;
import com.viaversion.viaversion.api.type.types.misc.ResolvableProfileType;
import com.viaversion.viaversion.api.type.types.misc.SoundEventType;
import com.viaversion.viaversion.api.type.types.misc.TagKeyType;
@@ -184,6 +190,8 @@ public final class Types {
public static final Type<int[]> VAR_INT_ARRAY_PRIMITIVE = new VarIntArrayType();
public static final VarLongType VAR_LONG = new VarLongType();
public static final BitSetType BIT_SET = new BitSetType(); // Generic length
/* MC Types */
public static final Type<byte[]> SERVERBOUND_CUSTOM_PAYLOAD_DATA = new RemainingBytesType(Short.MAX_VALUE);
@@ -192,6 +200,9 @@ public final class Types {
public static final Type<Key[]> IDENTIFIER_ARRAY = new ArrayType<>(IDENTIFIER);
public static final Type<Key> TAG_KEY = new TagKeyType();
public static final Type<ResolvableFloat> RESOLVABLE_FLOAT = new ResolvableFloatType();
public static final Type<ResolvableInt> RESOLVABLE_INT = new ResolvableIntType();
public static final Type<BlockPosition> BLOCK_POSITION1_8 = new BlockPositionType1_8();
public static final Type<BlockPosition> OPTIONAL_POSITION1_8 = new BlockPositionType1_8.OptionalBlockPositionType();
public static final Type<BlockPosition> BLOCK_POSITION1_14 = new BlockPositionType1_14();
@@ -199,6 +210,7 @@ public final class Types {
public static final Type<EulerAngle> ROTATIONS = new EulerAngleType();
public static final Type<Vector> VECTOR = new VectorType();
public static final Type<Vector3f> VECTOR3F = new Vector3fType();
public static final Type<Vector3d> VECTOR3D = new Vector3dType();
public static final Type<Quaternion> QUATERNION = new QuaternionType();
public static final Type<Vector3d> LOW_PRECISION_VECTOR = new LowPrecisionVectorType();
@Deprecated(forRemoval = true)
@@ -215,7 +227,11 @@ public final class Types {
public static final Type<Tag[]> TAG_ARRAY = new ArrayType<>(TAG);
public static final Type<Tag> OPTIONAL_TAG = TagType.OptionalTagType.type();
public static final Type<Tag> TEXT_COMPONENT_TAG = new TextComponentTagType(); // only strictly needed for hashing
public static final Type<Tag[]> TEXT_COMPONENT_TAG_ARRAY = new ArrayType<>(Types.TEXT_COMPONENT_TAG);
public static final Type<Tag> CUSTOM_CLICK_ACTION_TAG = new LengthPrefixedTagType(65536);
public static final FixedLengthArrayType<Tag> SIGN_TEXT = new FixedLengthArrayType<>(TAG, 4);
public static final Type<Tag[]> OPTIONAL_SIGN_TEXT = SIGN_TEXT.new OptionalFixedLengthArrayType();
public static final Type<Tag> TRUSTED_TAG = new TagType(false);
public static final Type<Tag> TRUSTED_OPTIONAL_TAG = TagType.OptionalTagType.trustedType();
@@ -280,6 +296,7 @@ public final class Types {
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_9 = new EntityDataListType(ENTITY_DATA1_9);
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_12 = new EntityDataListType(ENTITY_DATA1_12);
// No longer used past 1.20.2
public static final Type<Item> ITEM1_8 = new ItemType1_8();
public static final Type<Item> ITEM1_13 = new ItemType1_13();
@@ -31,7 +31,8 @@ import java.util.ArrayList;
import java.util.List;
public class ArrayType<T> extends Type<T[]> {
private final Type<T> elementType;
private static final int MAX_PRESIZED_LENGTH = 128;
protected final Type<T> elementType;
private final int maxLength;
public ArrayType(Type<T> type) {
@@ -63,10 +64,10 @@ public class ArrayType<T> extends Type<T[]> {
throw new IllegalArgumentException("Array length " + amount + " is longer than maximum " + maxLength);
}
return amount < Short.MAX_VALUE ? readArray(buffer, amount) : readList(buffer, amount);
return amount <= MAX_PRESIZED_LENGTH ? readArray(buffer, amount) : readList(buffer, amount);
}
private T[] readArray(ByteBuf buffer, int length) {
protected T[] readArray(ByteBuf buffer, int length) {
T[] array = createArray(length);
for (int i = 0; i < length; i++) {
array[i] = elementType.read(buffer);
@@ -111,4 +112,14 @@ public class ArrayType<T> extends Type<T[]> {
public ArrayType<T> withMaxLength(final int maxLength) {
return new ArrayType<>(this.getOutputClass(), this.elementType, maxLength);
}
static int checkLength(final int length, final int elementBytes, final int readable) {
if (length < 0) {
throw new IllegalArgumentException("Length " + length + " is negative");
}
if ((long) length * elementBytes > readable) {
throw new IllegalArgumentException("Length " + length + " is larger than readable bytes");
}
return length;
}
}
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.type.types;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.util.Arrays;
import java.util.BitSet;
@@ -39,17 +40,31 @@ public class BitSetType extends Type<BitSet> {
this.bytesLength = (int) Math.ceil(length / 8D);
}
public BitSetType() {
super(BitSet.class);
this.length = -1;
this.bytesLength = -1;
}
@Override
public BitSet read(ByteBuf buffer) {
final byte[] bytes = new byte[bytesLength];
buffer.readBytes(bytes);
return BitSet.valueOf(bytes);
if (this.length != -1) {
final byte[] bytes = new byte[bytesLength];
buffer.readBytes(bytes);
return BitSet.valueOf(bytes);
} else {
return BitSet.valueOf(Types.BYTE_ARRAY_PRIMITIVE.read(buffer));
}
}
@Override
public void write(ByteBuf buffer, BitSet object) {
Preconditions.checkArgument(object.length() <= length, "BitSet of length %s larger than max length %s", object.length(), length);
final byte[] bytes = object.toByteArray();
buffer.writeBytes(bytes.length == bytesLength ? bytes : Arrays.copyOf(bytes, bytesLength));
if (this.length != -1) {
Preconditions.checkArgument(object.length() <= length, "BitSet of length %s larger than max length %s", object.length(), length);
final byte[] bytes = object.toByteArray();
buffer.writeBytes(bytes.length == bytesLength ? bytes : Arrays.copyOf(bytes, bytesLength));
} else {
Types.BYTE_ARRAY_PRIMITIVE.write(buffer, object.toByteArray());
}
}
}
@@ -57,7 +57,7 @@ public class BooleanArrayType extends Type<boolean[]> {
@Override
public boolean[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
Preconditions.checkArgument(buffer.isReadable(length), "Length is larger than readable bytes");
final boolean[] array = new boolean[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readBoolean();
@@ -32,15 +32,30 @@ import io.netty.buffer.ByteBuf;
public class ByteArrayType extends Type<byte[]> {
private final int length;
private final int maxLength;
public ByteArrayType(final int length) {
super(byte[].class);
this.length = length;
this(length, -1);
}
public ByteArrayType() {
this(-1, -1);
}
private ByteArrayType(final int length, final int maxLength) {
super(byte[].class);
this.length = -1;
this.length = length;
this.maxLength = maxLength;
}
/**
* Returns a length-prefixed byte array type that rejects arrays longer than the given maximum.
*
* @param maxLength maximum array length
* @return length-prefixed byte array type with the given maximum length
*/
public static ByteArrayType withMaxLength(final int maxLength) {
return new ByteArrayType(-1, maxLength);
}
@Override
@@ -48,6 +63,7 @@ public class ByteArrayType extends Type<byte[]> {
if (this.length != -1) {
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
} else {
checkMaxLength(object.length);
Types.VAR_INT.writePrimitive(buffer, object.length);
}
buffer.writeBytes(object);
@@ -55,13 +71,20 @@ public class ByteArrayType extends Type<byte[]> {
@Override
public byte[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final int length = this.length == -1 ? checkMaxLength(Types.VAR_INT.readPrimitive(buffer)) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is larger than readable bytes");
final byte[] array = new byte[length];
buffer.readBytes(array);
return array;
}
private int checkMaxLength(final int length) {
if (maxLength != -1 && length > maxLength) {
throw new IllegalArgumentException("Byte array length " + length + " is longer than maximum " + maxLength);
}
return length;
}
@Override
public void write(final Ops ops, final byte[] value) {
ops.writeBytes(value);
@@ -76,4 +76,16 @@ public final class EnumType extends VarIntType {
public enum Fallback {
ZERO, WRAP, CLAMP
}
public final class EnumArrayType extends VarIntArrayType {
@Override
public void write(final Ops ops, final int[] value) {
ops.writeList(list -> {
for (final int ordinal : value) {
list.write(Types.STRING, nameFromId(ordinal));
}
});
}
}
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.type.types;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class FixedLengthArrayType<T> extends ArrayType<T> {
private final int length;
public FixedLengthArrayType(final Type<T> type, final int length) {
super(type);
this.length = length;
}
@Override
public T[] read(final ByteBuf buffer) {
return readArray(buffer, this.length);
}
@Override
public void write(final ByteBuf buffer, final T[] object) {
for (final T o : object) {
elementType.write(buffer, o);
}
}
public final class OptionalFixedLengthArrayType extends OptionalType<T[]> {
public OptionalFixedLengthArrayType() {
super(FixedLengthArrayType.this);
}
}
}
@@ -27,6 +27,8 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import static com.viaversion.viaversion.api.type.types.ArrayType.checkLength;
public class FloatArrayType extends Type<float[]> {
private final int length;
@@ -55,8 +57,7 @@ public class FloatArrayType extends Type<float[]> {
@Override
public float[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final int length = checkLength(this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length, Float.BYTES, buffer.readableBytes());
final float[] array = new float[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readFloat();
@@ -28,6 +28,8 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import static com.viaversion.viaversion.api.type.types.ArrayType.checkLength;
public class IntArrayType extends Type<int[]> {
private final int length;
@@ -56,8 +58,7 @@ public class IntArrayType extends Type<int[]> {
@Override
public int[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final int length = checkLength(this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length, Integer.BYTES, buffer.readableBytes());
final int[] array = new int[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readInt();
@@ -28,6 +28,8 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import static com.viaversion.viaversion.api.type.types.ArrayType.checkLength;
public class LongArrayType extends Type<long[]> {
private final int length;
@@ -43,8 +45,7 @@ public class LongArrayType extends Type<long[]> {
@Override
public long[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final int length = checkLength(this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length, Long.BYTES, buffer.readableBytes());
return readFixedLength(buffer, length);
}
@@ -34,6 +34,7 @@ import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
public class HashedItemType1_21_5 extends Type<HashedItem> {
private static final int MAX_DATA_TYPE_ID = 255; // Needs adjusting if we ever get beyond this
public HashedItemType1_21_5() {
super(HashedItem.class);
@@ -51,7 +52,7 @@ public class HashedItemType1_21_5 extends Type<HashedItem> {
final int addedComponentsSize = Limit.max(Types.VAR_INT.readPrimitive(buffer), 256);
final Int2IntMap dataHashes = new Int2IntOpenHashMap(addedComponentsSize);
for (int i = 0; i < addedComponentsSize; i++) {
final int dataType = Types.VAR_INT.readPrimitive(buffer);
final int dataType = readDataType(buffer);
final int hash = Types.INT.readPrimitive(buffer);
dataHashes.put(dataType, hash);
}
@@ -59,12 +60,20 @@ public class HashedItemType1_21_5 extends Type<HashedItem> {
final int removedComponentsSize = Limit.max(Types.VAR_INT.readPrimitive(buffer), 256);
final IntSet removedData = new IntOpenHashSet(removedComponentsSize);
for (int i = 0; i < removedComponentsSize; i++) {
final int dataType = Types.VAR_INT.readPrimitive(buffer);
final int dataType = readDataType(buffer);
removedData.add(dataType);
}
return new HashedStructuredItem(id, amount, dataHashes, removedData);
}
private static int readDataType(final ByteBuf buffer) {
final int dataType = Types.VAR_INT.readPrimitive(buffer);
if (dataType < 0 || dataType > MAX_DATA_TYPE_ID) {
throw new IllegalArgumentException("Invalid data component type " + dataType);
}
return dataType;
}
@Override
public void write(final ByteBuf buffer, final HashedItem value) {
if (value.isEmpty()) {
@@ -34,7 +34,6 @@ import io.netty.buffer.ByteBuf;
// Very similar to normal items (and just results in an item), except it allows non-positive amounts and has id/amount swapped because ???
public final class ItemCostType1_20_5 extends Type<Item> {
private static final StructuredData<?>[] EMPTY_DATA_ARRAY = new StructuredData[0];
private final Type<StructuredData<?>[]> dataArrayType;
public ItemCostType1_20_5(final Type<StructuredData<?>[]> dataArrayType) {
@@ -54,7 +53,8 @@ public final class ItemCostType1_20_5 extends Type<Item> {
public void write(final ByteBuf buffer, final Item object) {
Types.VAR_INT.writePrimitive(buffer, object.identifier());
Types.VAR_INT.writePrimitive(buffer, object.amount());
dataArrayType.write(buffer, object.dataContainer().data().values().toArray(EMPTY_DATA_ARRAY));
// Item costs are exact-match predicates without removal markers, so empty data can't be written
dataArrayType.write(buffer, object.dataContainer().data().values().stream().filter(StructuredData::isPresent).toArray(StructuredData[]::new));
}
public static final class OptionalItemCostType extends OptionalType<Item> {
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types.item;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
@@ -55,6 +56,16 @@ public class ItemTemplateType26_1 extends ItemType1_20_5 {
writeData(buffer, object);
}
@Override
public void write(final Ops ops, final Item item) {
// Unlike item stacks, templates omit the default count
ops.writeMap(map -> {
map.write("id", Types.IDENTIFIER, ops.context().registryAccess().item(item.identifier()))
.writeOptional("count", Types.VAR_INT, item.amount(), 1);
writeComponents(map, item);
});
}
public static final class OptionalItemTemplateType extends OptionalType<Item> {
public OptionalItemTemplateType(final Type<Item> type) {
@@ -127,22 +127,25 @@ public class ItemType1_20_5 extends Type<Item> {
ops.writeMap(map -> {
map.write("id", Types.IDENTIFIER, ops.context().registryAccess().item(item.identifier()))
.write("count", Types.VAR_INT, item.amount());
writeComponents(map, item);
});
}
if (item.dataContainer().isEmpty()) {
return;
}
protected void writeComponents(final Ops.MapSerializer map, final Item item) {
if (item.dataContainer().isEmpty()) {
return;
}
map.writeMap("components", components -> {
for (final StructuredData<?> data : item.dataContainer().data().values()) {
String key = Key.namespaced(data.key().identifier());
if (data.isEmpty()) {
key = "!" + key;
}
//noinspection unchecked
components.write(key, (Type<StructuredData<?>>) dataType, data);
map.writeMap("components", components -> {
for (final StructuredData<?> data : item.dataContainer().data().values()) {
String key = Key.namespaced(data.key().identifier());
if (data.isEmpty()) {
key = "!" + key;
}
});
//noinspection unchecked
components.write(key, (Type<StructuredData<?>>) dataType, data);
}
});
}
@@ -76,7 +76,7 @@ public class StructuredDataType extends Type<StructuredData<?>> implements Struc
}
<T> StructuredData<T> readData(final ByteBuf buffer, final StructuredDataKey<T> key, final int id) {
return StructuredData.of(key, key.type().read(buffer), id);
return StructuredData.of(key, key.type().readTrackingDepth(buffer), id);
}
public DataFiller filler(final Protocol<?, ?, ?, ?> protocol) {
@@ -0,0 +1,49 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.type.types.math;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class Vector3dType extends Type<Vector3d> {
public Vector3dType() {
super(Vector3d.class);
}
@Override
public Vector3d read(final ByteBuf buffer) {
final double x = buffer.readDouble();
final double y = buffer.readDouble();
final double z = buffer.readDouble();
return new Vector3d(x, y, z);
}
@Override
public void write(final ByteBuf buffer, final Vector3d object) {
buffer.writeDouble(object.x());
buffer.writeDouble(object.y());
buffer.writeDouble(object.z());
}
}
@@ -31,6 +31,10 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.io.FastByteBufInputStream;
import com.viaversion.viaversion.io.FastByteBufOutputStream;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -72,7 +76,8 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
}
final TagLimiter tagLimiter = TagLimiter.create(maxBytes, TagLimiter.DEFAULT_MAX_NESTING_LEVEL);
return CompoundTag.read(new FastByteBufInputStream(buffer), tagLimiter, 0);
final DataInput in = TagType.USE_JAVA_DATA_IO ? new ByteBufInputStream(buffer) : new FastByteBufInputStream(buffer);
return CompoundTag.read(in, tagLimiter, 0);
}
public static void write(final ByteBuf buffer, final Tag tag, final @Nullable String name) throws IOException {
@@ -81,7 +86,7 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
return;
}
final FastByteBufOutputStream out = new FastByteBufOutputStream(buffer);
final DataOutput out = TagType.USE_JAVA_DATA_IO ? new ByteBufOutputStream(buffer) : new FastByteBufOutputStream(buffer);
out.writeByte(tag.getTagId());
if (name != null) {
out.writeUTF(name);
@@ -26,9 +26,12 @@ import com.viaversion.viaversion.api.minecraft.ProfileKey;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ByteArrayType;
import io.netty.buffer.ByteBuf;
public class ProfileKeyType extends Type<ProfileKey> {
private static final ByteArrayType PUBLIC_KEY_TYPE = ByteArrayType.withMaxLength(512);
private static final ByteArrayType KEY_SIGNATURE_TYPE = ByteArrayType.withMaxLength(4096);
public ProfileKeyType() {
super(ProfileKey.class);
@@ -36,14 +39,14 @@ public class ProfileKeyType extends Type<ProfileKey> {
@Override
public ProfileKey read(final ByteBuf buffer) {
return new ProfileKey(buffer.readLong(), Types.BYTE_ARRAY_PRIMITIVE.read(buffer), Types.BYTE_ARRAY_PRIMITIVE.read(buffer));
return new ProfileKey(buffer.readLong(), PUBLIC_KEY_TYPE.read(buffer), KEY_SIGNATURE_TYPE.read(buffer));
}
@Override
public void write(final ByteBuf buffer, final ProfileKey object) {
buffer.writeLong(object.expiresAt());
Types.BYTE_ARRAY_PRIMITIVE.write(buffer, object.publicKey());
Types.BYTE_ARRAY_PRIMITIVE.write(buffer, object.keySignature());
PUBLIC_KEY_TYPE.write(buffer, object.publicKey());
KEY_SIGNATURE_TYPE.write(buffer, object.keySignature());
}
public static final class OptionalProfileKeyType extends OptionalType<ProfileKey> {
@@ -0,0 +1,66 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.type.types.misc;
import com.viaversion.viaversion.api.minecraft.ResolvableFloat;
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 final class ResolvableFloatType extends Type<ResolvableFloat> {
public ResolvableFloatType() {
super(ResolvableFloat.class);
}
@Override
public ResolvableFloat read(final ByteBuf buffer) {
if (buffer.readBoolean()) {
return ResolvableFloat.of(Types.FLOAT.readPrimitive(buffer));
} else {
return ResolvableFloat.of(Types.STRING.read(buffer));
}
}
@Override
public void write(final ByteBuf buffer, final ResolvableFloat value) {
if (value.isLeft()) {
buffer.writeBoolean(true);
Types.FLOAT.writePrimitive(buffer, value.left());
} else {
buffer.writeBoolean(false);
Types.IDENTIFIER.write(buffer, Key.of(value.right()));
}
}
@Override
public void write(final Ops ops, final ResolvableFloat value) {
if (value.isLeft()) {
Types.FLOAT.write(ops, value.left());
} else {
Types.IDENTIFIER.write(ops, Key.of(value.right()));
}
}
}
@@ -0,0 +1,66 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.type.types.misc;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
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 final class ResolvableIntType extends Type<ResolvableInt> {
public ResolvableIntType() {
super(ResolvableInt.class);
}
@Override
public ResolvableInt read(final ByteBuf buffer) {
if (buffer.readBoolean()) {
return ResolvableInt.of(Types.INT.readPrimitive(buffer));
} else {
return ResolvableInt.of(Types.STRING.read(buffer));
}
}
@Override
public void write(final ByteBuf buffer, final ResolvableInt value) {
if (value.isLeft()) {
buffer.writeBoolean(true);
Types.INT.writePrimitive(buffer, value.left());
} else {
buffer.writeBoolean(false);
Types.IDENTIFIER.write(buffer, Key.of(value.right()));
}
}
@Override
public void write(final Ops ops, final ResolvableInt value) {
if (value.isLeft()) {
Types.INT.write(ops, value.left());
} else {
Types.IDENTIFIER.write(ops, Key.of(value.right()));
}
}
}
@@ -45,11 +45,14 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.io.FastByteBufInputStream;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import java.io.DataInput;
import java.io.IOException;
import java.util.Map;
public class TagType extends Type<Tag> {
static final boolean USE_JAVA_DATA_IO = Runtime.version().feature() >= 24; // Improved by a lot in JDK 24
private final int maxBytes;
public TagType() {
@@ -70,7 +73,8 @@ public class TagType extends Type<Tag> {
final TagLimiter tagLimiter = TagLimiter.create(this.maxBytes, TagLimiter.DEFAULT_MAX_NESTING_LEVEL);
try {
return TagRegistry.read(id, new FastByteBufInputStream(buffer), tagLimiter, 0);
final DataInput in = USE_JAVA_DATA_IO ? new ByteBufInputStream(buffer) : new FastByteBufInputStream(buffer);
return TagRegistry.read(id, in, tagLimiter, 0);
} catch (final IOException e) {
if (Via.getManager().isDebug()) {
throw new RuntimeException(e);
@@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_
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.data.version.StructuredDataKeys26_2;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys26_3;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_20_5;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_11;
@@ -34,6 +35,7 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_3;
/**
* Holds versioned accessors for highly volatile types, specifically around items and data components.
@@ -53,4 +55,5 @@ public final class VersionedTypes {
public static final Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes1_21_11> V1_21_11 = new Types1_20_5<>(StructuredDataKeys1_21_11::new, EntityDataTypes1_21_11::new);
public static final Types26_1<StructuredDataKeys1_21_11, EntityDataTypes26_1> V26_1 = new Types26_1<>(StructuredDataKeys1_21_11::new, EntityDataTypes26_1::new);
public static final Types26_1<StructuredDataKeys26_2, EntityDataTypes26_1> V26_2 = new Types26_1<>(StructuredDataKeys26_2::new, EntityDataTypes26_1::new);
public static final Types26_1<StructuredDataKeys26_3, EntityDataTypes26_3> V26_3 = new Types26_1<>(StructuredDataKeys26_3::new, EntityDataTypes26_3::new);
}
@@ -39,9 +39,7 @@ public interface Copyable {
final int length = Array.getLength(object);
final Object copy = Array.newInstance(componentType, length);
if (componentType.isPrimitive()) {
for (int i = 0; i < length; i++) {
Array.set(copy, i, Array.get(object, i));
}
System.arraycopy(object, 0, copy, 0, length);
} else {
// See if we need to copy elements, too
for (int i = 0; i < length; i++) {
@@ -29,11 +29,11 @@ public class EitherImpl<X, Y> implements Either<X, Y> {
private final X left;
private final Y right;
protected EitherImpl(final X left, final Y value) {
protected EitherImpl(final X left, final Y right) {
this.left = left;
this.right = value;
Preconditions.checkArgument(left == null || value == null, "Either.left and Either.right are both present");
Preconditions.checkArgument(left != null || value != null, "Either.left and Either.right are both null");
this.right = right;
Preconditions.checkArgument(left == null || right == null, "Either.left and Either.right are both present");
Preconditions.checkArgument(left != null || right != null, "Either.left and Either.right are both null");
}
@Override
@@ -71,6 +71,7 @@ public final class EntityTypeUtil {
final int id = mappings.mappedId(type.identifier());
Preconditions.checkArgument(id != -1, "Entity type %s has no id", type.identifier());
Preconditions.checkArgument(id < typesToFill.length, "Types array too small (missing enum entry?). Tried setting id %s into array of size %s", id, typesToFill.length);
idSetter.setId(type, id);
typesToFill[id] = type;
}
@@ -0,0 +1,53 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.util;
public final class NestingLimiter {
private static final ThreadLocal<int[]> STATE = ThreadLocal.withInitial(() -> new int[]{0, -1}); // Current depth, max depth
/**
* Sets the max depth for reads on the current thread.
*
* @param maxDepth max depth, or -1 for no limit
* @return the previous max depth, to be set again once done
*/
public static int setMaxDepth(final int maxDepth) {
final int[] state = STATE.get();
final int previous = state[1];
state[1] = maxDepth;
return previous;
}
public static void increment() {
final int[] state = STATE.get();
if (state[1] != -1 && state[0] >= state[1]) {
throw new IllegalArgumentException("Data is nested too deeply");
}
state[0]++;
}
public static void decrement() {
STATE.get()[0]--;
}
}
@@ -161,6 +161,7 @@ public final class PipelineUtil {
return null;
}
@Deprecated(forRemoval = true)
public static @Nullable ChannelHandlerContext getPreviousContext(String name, ChannelPipeline pipeline) {
String previous = null;
for (String entry : pipeline.toMap().keySet()) {
@@ -24,7 +24,9 @@ package com.viaversion.viaversion.util;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -60,6 +62,12 @@ public interface Rewritable {
return mappings == null ? itemId : (clientbound ? mappedIdentifier(mappings, itemId) : unmappedIdentifier(mappings, itemId));
}
static @Nullable Item rewriteItem(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound, final Item item) {
final ItemRewriter<?> rewriter = protocol.getItemRewriter();
return rewriter == null ? item
: (clientbound ? rewriter.handleItemToClient(connection, item) : rewriter.handleItemToServer(connection, item));
}
static Int2IntFunction itemRewriteFunction(final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return protocol.getMappingData().getItemMappings() == null ? Int2IntFunction.identity()
: (clientbound ? protocol.getMappingData()::getNewItemId : protocol.getMappingData()::getOldItemId);
@@ -72,7 +80,7 @@ public interface Rewritable {
static Int2IntFunction soundRewriteFunction(final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return protocol.getMappingData().getSoundMappings() == null ? Int2IntFunction.identity()
: (clientbound ? protocol.getMappingData().getSoundMappings()::getNewId : protocol.getMappingData()::getOldSoundId);
: (clientbound ? protocol.getMappingData().getSoundMappings()::getNewId : protocol.getMappingData().getSoundMappings().inverse()::getNewId);
}
static Int2IntFunction entityRewriteFunction(final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
@@ -44,11 +44,22 @@ public final class UUIDUtil {
}
public static @Nullable UUID parseUUID(final String uuidString) {
try {
return UUID.fromString(uuidString);
} catch (final IllegalArgumentException e) {
// Check the format beforehand instead of catching the exception, exceptions are expensive
if (uuidString.length() != 36) {
return null;
}
for (int i = 0; i < 36; i++) {
final char c = uuidString.charAt(i);
if (i == 8 || i == 13 || i == 18 || i == 23) {
if (c != '-') {
return null;
}
} else if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')) {
return null;
}
}
return UUID.fromString(uuidString);
}
/**
+1 -2
View File
@@ -7,8 +7,7 @@ repositories {
}
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.4.2")
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.6.1")
// A nice no-conflict comment for patching in downgrading
}
@@ -1,6 +1,5 @@
plugins {
`java-library`
`jvm-test-suite`
}
tasks {
Whitespace-only changes.
+2 -1
View File
@@ -1,6 +1,7 @@
plugins {
base
id("via.build-logic")
id("via.base-conventions") apply false
id("via.shadow-conventions") apply false
}
allprojects {
@@ -22,6 +22,7 @@ import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.ProtocolStorables1_21;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -55,7 +56,12 @@ public class PlayerChangeItemListener extends ViaBukkitListener {
}
protected EfficiencyAttributeStorage getEfficiencyStorage(final UserConnection connection) {
return connection != null ? connection.get(EfficiencyAttributeStorage.class) : null;
if (connection == null || !connection.isActive()) {
return null;
}
final ProtocolStorables1_21 storables = connection.storables(Protocol1_20_5To1_21.class);
return storables.efficiencyAttributes();
}
void sendAttributeUpdate(final Player player, @Nullable final ItemStack item, final Slot slot) {
Loaded 100 of 312 files, more files were not shown because too many files have changed in this diff. Show more