Compare commits

...
384 Commits
Author SHA1 Message Date
Nassim Jahnke 4e021f23ad 5.12.2 Release 2026-10-27 16:24:13 +01:00
Nassim Jahnke 9bf8a6b447 Remove map decorations from hover events in 26.3->26.2 2026-10-27 16:24:02 +01:00
olcxja 0452ac26f3 Fix unknown block states in registry data for pre-26.3 clients (#1372) 2026-10-27 16:03:46 +01:00
Nassim Jahnke 4938de8a33 Add more vanilla limits/sanity checks 2026-10-27 15:36:38 +01:00
Nassim Jahnke c3bdf7230c Fix project id 2026-10-21 13:35:56 +02:00
Nassim Jahnke 104d68c29f 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:29:09 +02:00
Nassim Jahnke c7702cc5a3 Update VV usage 2026-10-18 22:13:36 +02:00
Florian Reuth 90fb84e012 Fix items atlas text components in 1.21.11->1.21.9 being invalid (#1364) 2026-10-18 22:05:44 +02:00
Florian Reuth 2aec24449e Add missing creative item backup code to 1.21.2->1.21 item handling (#1358) 2026-10-12 18:58:31 +02:00
Nassim Jahnke cbafc0564e Replace block state providers with dummy entries
They're never shown or used by the client.

Closes #1357
2026-10-11 20:36:51 +02:00
Florian Reuth e7b588b965 Handle long arrays inside lists in 1.12->1.11.1 (#1355) 2026-10-11 20:15:24 +02:00
Florian Reuth d85de3461a Fix spawner handling registering in 1.11->1.10 (#1354) 2026-10-11 20:14:31 +02:00
Florian Reuth 924179d2af Always rewrite enchantments in 1.19->1.18.2 (#1356) 2026-10-11 20:10:20 +02:00
mfishma 465dc5bbef Fix 26.3 map decorations not getting restored (#1350) 2026-10-11 09:27:38 +02:00
Rocco 71038072ed Save original int map ID if conversion is lossy in 1.13->1.12 (#1341) 2026-10-11 09:26:05 +02:00
mfishma 6cdf663490 Map poplar leaves backwards to varied leaves in 26.3->26.2 2026-10-09 16:44:14 +02:00
Nassim Jahnke 0ba32cf4a5 Handle experimental minecart velocity in 1.21.2->1.21
Fixes #1333
2026-10-09 15:46:04 +02:00
Nassim Jahnke 5b1c323274 Bump version to 5.12.2-SNAPSHOT 2026-10-09 15:35:31 +02:00
Nassim Jahnke 1d954e23ab Separate Fabric platform on modrinth
... or it'll fail when specifying versions below 1.14
2026-10-08 16:05:02 +02:00
Nassim Jahnke cece459a36 5.12.1 Release 2026-10-08 15:42:33 +02:00
TomoyaandNassim Jahnke d413b4af3a Fix some enchantment term rewriting in 26.3->26.2 (#1346)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-10-08 15:13:55 +02:00
Florian Reuth ec63e9f808 Back up non-default canDestroyBlocksInCreative in 1.21.5->1.21.4 (#1345) 2026-10-01 18:37:24 +02:00
Florian Reuth 5a84625078 Backup wolf collar in 1.21.5->1.21.4 (#1344) 2026-10-01 18:36:35 +02:00
Florian Reuth a36dfbc799 Fix conditions swap in kinetic weapon restore in 1.21.11->1.21.9 (#1343) 2026-10-01 14:56:13 +02:00
Florian Reuth db6fc3d60d Fix jukebox_playable restore in 1.21->1.20.5 (#1342) 2026-10-01 14:54:58 +02:00
Nassim Jahnke 9a5b384e55 Remove no longer needed head yaw packet for mannequins 2026-09-29 18:41:36 +02:00
Florian Reuth f801af36f8 Update VV api usage (#1340) 2026-09-29 18:41:17 +02:00
Rocco 883ca8dc01 Send player head yaw on spawn in 1.20.2->1.20 (#1337) 2026-09-29 18:27:35 +02:00
Florian Reuth 41fbca556e Handle tag displays without tag key in 26.3->26.2 (#1336) 2026-09-29 18:24:11 +02:00
Rocco 32e81d9887 Fix 1.12.2 red=0 dust particle color (#1323) 2026-09-29 18:19:52 +02:00
terbin 906b3afa0b Add statistic mappings for 1.17->1.16.2 (#1339) 2026-09-29 14:46:47 +02:00
Rocco ddc776c284 Change resin trim material to gold for 1.21.2 clients (#1330) 2026-09-28 19:54:49 +02:00
Florian Reuth c73db36674 Update VV api usage (#1335) 2026-09-28 19:35:18 +02:00
Happy-FZM 7bb4a5d69c Move Dyeable to correct version 2026-09-25 15:01:13 +02:00
Rocco 4bb1b681e6 Add potion color mappings for new 1.19.4 colors (#1329) 2026-09-22 21:58:28 +02:00
Nassim Jahnke 53c43db7ad Add missing tags across protocols 2026-09-20 13:08:36 +02:00
Florian Reuth 3f9073ee68 Always show end credits in 1.21->1.20.5 (#1324) 2026-09-20 13:00:13 +02:00
Nassim Jahnke 283e40d32d Map cushion to carpet falling block
Closes #1322
2026-09-19 17:27:04 +02:00
Rocco 53105e644d Update armor from containers in 1.21.2->1.21 (#1321) 2026-09-19 11:41:11 +02:00
Rocco cd4470c7df Calculate painting offsets in 1.19->1.18.2 (#1313) 2026-09-19 11:39:27 +02:00
Nassim Jahnke 64e049fa0f Bump version to 4.12.1-SNAPSHOT 2026-09-19 11:12:16 +02:00
Nassim Jahnke 321f708674 5.12.0 Release 2026-09-18 16:45:21 +02:00
Nassim Jahnke de7fa4e6a3 Remove brewing stand total fuel and total brewing time 2026-09-16 11:51:03 +02:00
Florian Reuth a3e47e2d66 Backup/Restore new map decoration types
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-14 22:22:21 +02:00
Nassim Jahnke f638e8488d Update mappings 2026-09-14 17:08:41 +02:00
Nassim Jahnke 91f5a62de0 Update map decoration type ids 2026-09-14 17:06:48 +02:00
Florian Reuth 8e09ed3aea Move client_tick_end emulation to movement packets during movement
Prevents sending of multiple position packets per client tick which 26.3+ no longer allows.

Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 18:01:16 +02:00
Florian Reuth 6c97db3867 Handle block_state_property registry changes
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 15:38:40 +02:00
Florian Reuth c0305804a4 Replace mask type in player_chat
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 14:42:35 +02:00
Florian Reuth 6518739c21 Update VV usage
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 14:03:32 +02:00
Florian Reuth 5436cc0062 Handle new type in player_action
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 13:37:32 +02:00
Florian Reuth 138b2013d6 Backup inconvertible item data for creative clients
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 12:56:23 +02:00
Nassim Jahnke 59eb5ccbc8 Fix sign update 2026-09-12 12:39:23 +02:00
Nassim Jahnke 446d878671 Add translation mappings 2026-09-12 12:35:41 +02:00
Nassim Jahnke a0fa6a5e04 Remove remaining new data in hover events 2026-09-12 12:33:45 +02:00
Florian Reuth 00cbc4d149 Update template protocol
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 12:02:00 +02:00
Florian Reuth 336327a25c Remove worldgen/block_state_provider registry
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 11:59:16 +02:00
Florian Reuth da0c9eebde Handle decorated_pot block entity data
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-12 00:22:43 +02:00
Florian Reuth 36ca84041d Fix UPDATE_ADVANCEMENTS position calculation
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-11 23:14:24 +02:00
Florian Reuth 631142f3da Handle EXPLODE play_sound boolean
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-11 22:25:01 +02:00
Florian Reuth ca18e1e713 Update mapped string argument type names
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-11 21:57:03 +02:00
Nassim Jahnke 14958dbdd8 Fix swing animation handling 2026-09-10 16:32:21 +02:00
Nassim Jahnke 7ee2e15325 26.3-pre-3 2026-09-10 16:32:21 +02:00
Nassim Jahnke fb90e750d5 Handle new particle randomization 2026-09-10 16:32:21 +02:00
Nassim Jahnke 5533e61c32 26.3-pre2 2026-09-10 16:32:21 +02:00
Nassim Jahnke 9105fc4d79 26.3-pre-1 2026-09-10 16:32:21 +02:00
Nassim Jahnke 86be811cfc Finish 26.3-snapshot-10 2026-09-10 16:32:21 +02:00
Nassim Jahnke 7025027115 WIP 26.3-snapshot-10 2026-09-10 16:32:21 +02:00
Nassim Jahnke 6466affb8b 26.3-snapshot-9 2026-09-10 16:32:20 +02:00
Nassim Jahnke a0ab595d9b 26.3-snapshot-7 2026-09-10 16:32:20 +02:00
Nassim Jahnke 4b7b039621 26.3-snapshot-5 2026-09-10 16:32:20 +02:00
Nassim Jahnke 9a0c78b25f 26.3-snapshot-4 2026-09-10 16:32:20 +02:00
Nassim Jahnke d9c4d1c151 Try to handle multiple steps better 2026-09-10 16:32:20 +02:00
Nassim Jahnke f919050171 26.3-snapshot-3 2026-09-10 16:32:20 +02:00
Nassim Jahnke 3c3040f22d 26.3-snapshot-2 2026-09-10 16:32:20 +02:00
Nassim Jahnke d63f1d1fad 26.3-snapshot-1 (minus item mappings) 2026-09-10 16:32:20 +02:00
icicle1133 9265832edf Null-check entity_properties predicate in 26.2->26.1 (#1317) 2026-09-07 17:51:06 +02:00
Nassim Jahnke 5615d0591f Remove 1.14->1.13 cat name 2026-09-04 21:04:57 +02:00
Rocco e7d8703f86 Rewrite cat to ocelot variants in 1.14->1.13.2 (#1311) 2026-09-04 21:04:01 +02:00
Creeam 441c7f831f Rename block tags 26.1 to 1.21.11 for client prediction (#1309) 2026-08-29 13:30:28 +02:00
fedpol1 87fb4c7e25 Handle environment attributes in timelines on the 26.1->1.21.11 step (#1307) 2026-08-28 16:48:19 +02:00
Nassim Jahnke 1aa00f4d1b [ci skip] Build script updates 2026-08-23 15:15:34 +02:00
Nassim Jahnke 4ad05a4470 Update VV usage 2026-08-05 17:47:24 +02:00
Nassim Jahnke 8fb466022a Fix held block rewriting in 1.13->1.12
Fixes #1303
2026-07-29 10:12:17 +02:00
Nassim Jahnke 799d8945a2 Remove warning when trying to open stonecutter 2026-07-29 09:53:12 +02:00
Nassim Jahnke 4bc4a4c942 Flip respawn_anchor_works default
Fixes #1302
2026-07-23 21:19:04 +02:00
Term4 483c0ec0d6 Don't send legacy clients their own death event (#1296) 2026-07-18 19:33:37 +02:00
amy ef665d2f95 Prevent Mannequin names from having formatting in 1.12.2 (#1298) 2026-07-18 10:00:48 +02:00
Nassim Jahnke 8fc519b781 Clean up build scripts 2026-07-16 10:38:37 +02:00
Nassim Jahnke fba3a6986a Bump version to 5.11.1-SNAPSHOT 2026-07-16 10:37:53 +02:00
Nassim Jahnke c1620746bc 5.11.0 Release 2026-07-12 18:05:35 +02:00
Nassim Jahnke 59860ebf01 Fix manual blockstates-1.13 loading 2026-07-12 18:04:40 +02:00
Nassim Jahnke a2eecded20 Update to mapping format v2 2026-07-12 10:56:35 +02:00
Nassim Jahnke d63f7e1575 Remove 1.21.11 enchantment effects
Fixes #1281
2026-07-09 20:58:17 +02:00
Nassim Jahnke f04e115b95 Bump version to 5.11.0-SNAPSHOT 2026-07-09 15:19:15 +02:00
Nassim Jahnke 54897e7e5f Update VV usage 2026-07-09 15:14:06 +02:00
Nassim Jahnke 0e53ac9693 Split multi-line text displays into multiple entities
Fixes #767
2026-07-09 12:35:27 +02:00
Nassim Jahnke d975df4d27 Fix creative mode clear action in 1.21.2->1.21
Fixes #940
2026-07-08 19:25:51 +02:00
Nassim Jahnke 206a5b4171 Pass new item and entity names as translatable
This removes the itemnames and entitynames sections from mapping data and instead allows for easier changes via resource packs.

For 1.20.5+ clients, entities use the `vb.entity.<type>` translate key; items use `vg.item.<type>`. The old-style string (e.g. "26.2 Sulfur" is added into the `fallback` field).

For clients below 1.20.5, the old style string is put directly into the `translate` field.
2026-07-08 18:35:39 +02:00
Nassim Jahnke 9e8a958de2 Add item names as translate components instead
Fixes #659
2026-07-08 16:21:13 +02:00
Nassim Jahnke 4e0618b2e5 Remove new environment attributes from registry data
Fixes #1292
2026-07-08 16:05:38 +02:00
Nassim Jahnke d6a3338731 Always map to unpowered_comparator in 1.13->1.12
The powered_comparator block goes unused, the state is instead in the powered property
Fixes #1222
Properly fixes #524
2026-07-08 15:09:18 +02:00
mfishmaandNassim Jahnke df630e8828 Scale new baby mobs down on older clients (#1268)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-07-07 10:46:56 +02:00
Nassim Jahnke e1802a4ebc Fix sulfur caves legacy mapping 2026-07-06 12:04:55 +02:00
Florian Reuth 0bd189cb45 Update damage event entity id types in 1.19.4->.3 (#1291) 2026-07-05 20:55:44 +02:00
Nassim Jahnke 8d067dce31 Optimize block checking in chunk packets 2026-07-05 12:00:15 +02:00
Nassim Jahnke a5e622e670 Skip heavy 1.20.5-1.21.4 serverbound item handling on 1.21.5+ servers
This instead forces (only) hashed item data through
2026-07-03 19:57:23 +02:00
Nassim Jahnke 6f7a43d3a5 Move off 1.13 piston handler data loading; don't fully parse and re-serialize mapped item names 2026-07-03 13:01:30 +02:00
Nassim Jahnke f0ffd17df3 Fix code of conduct written tag type 2026-07-02 13:00:46 +02:00
booky 921f04c88c Send empty block entity for beds in 26.2->26.1 (#1286) 2026-07-01 21:53:58 +02:00
Nassim Jahnke bea4db86f1 Update VV usage 2026-06-20 18:06:39 +02:00
Florian Reuth 7709085bb6 Remove new sulfur cube archetype registry in 26.2->26.1 (#1280) 2026-06-20 09:43:40 +02:00
Nassim Jahnke b5db485ecc 5.10.0 Release 2026-06-19 19:18:19 +02:00
Nassim Jahnke d219cd75be Map sulfur cube to slime 2026-06-19 19:18:19 +02:00
Nassim Jahnke 72ccb3bd85 Update mappings 2026-06-19 19:18:19 +02:00
Nassim Jahnke bdd786e473 Update deps 2026-06-19 19:18:19 +02:00
Florian Reuth 97f1419156 Update BackwardsRegistryRewriter for 1.21.11+ registry structure 2026-06-19 19:18:19 +02:00
Nassim Jahnke aaf080d065 Update mappings 2026-06-19 19:18:19 +02:00
Nassim Jahnke b30a2e6733 26.2-pre-1 2026-06-19 19:18:18 +02:00
Nassim Jahnke 58c7f4debc 26.2-snapshot-7 2026-06-19 19:18:18 +02:00
Nassim Jahnke 67c08b86b6 26.2-snapshot-5 2026-06-19 19:18:18 +02:00
Nassim Jahnke 9a855c3278 26.2-snapshot-4 2026-06-19 19:18:18 +02:00
Nassim Jahnke 570b3b7afd 26.2-snapshot-3 2026-06-19 19:18:18 +02:00
Nassim Jahnke 5834077e93 26.2-snapshot-1 2026-06-19 19:18:17 +02:00
Florian Reuth 59abf8bd18 Fix tag updating in 1.21.6->1.21.5 (#1277) 2026-06-15 11:17:05 +02:00
Term4 33d3b1db9c Round instead of truncating in toLegacyVelocity (#1272) 2026-06-12 17:28:11 +02:00
Nassim Jahnke 5255394ed6 Track mid-game spectator gamemode change in 26.1->1.21.11
Fixes #1267
2026-06-07 12:49:00 +02:00
Nassim Jahnke c5713f915d Move velocity explosion packet out of bounds in 1.21.2->1.21 2026-06-07 12:37:08 +02:00
Nassim Jahnke e651e1cef9 Update VV usage 2026-05-25 09:33:52 +02:00
Gubis Zsombor Dániel c3f6271a0d Fix NPE in BlockRewriter1_20_2 when block entity has null tag (#1262) 2026-05-19 10:21:03 +02:00
RK_01 1508cd2820 [ci skip] Remove redundant types (#1259) 2026-05-08 19:07:16 +02:00
Nassim Jahnke bc7f3607c6 Track gamemode in 1.20.5 protocol 2026-05-08 19:05:55 +02:00
Nassim Jahnke 95d53b7f01 5.9.1 Release 2026-05-04 20:31:09 +02:00
Nassim Jahnke c4ac1b0560 Add hashed item shortcut in 1.21.5->1.21.4 2026-05-03 16:00:40 +02:00
Nassim Jahnke 8ee6391ff9 Remove ChunkLightStorage reflection 2026-05-03 12:21:56 +02:00
Florian Reuth 7700afb479 Move configuration state tracking into shared registrations (#1249) 2026-05-02 09:49:45 +02:00
Nassim Jahnke 5361c019f2 Fix shouldered parrot tracking in 1.21.9->1.21.7
Fixes #1257
2026-04-27 15:50:53 +02:00
Nassim Jahnke 041f7f933b Fix toggled advance_time handling
Fixes #1256
2026-04-27 15:40:18 +02:00
Kichura 48ad4e4aa3 [ci skip] Update action files (#1253) 2026-04-26 16:19:27 +02:00
Nassim Jahnke 358288f8f7 [ci skip] Add agents.md file 2026-04-26 16:16:51 +02:00
Beanes e46cf56e52 Cancel non-player bed sleep data in 1.14->1.13 (#1252) 2026-04-22 20:03:45 +02:00
BT ab9d1d26f3 Use TagRewriter in 1.14->1.13.2 (#1251) 2026-04-21 10:58:10 +02:00
Nassim Jahnke 65b2c30c7e Remove copper golem data in 1.21.9->1.21.7 2026-04-21 10:51:56 +02:00
Nassim Jahnke 9af3076c54 5.9.0 Release 2026-04-19 15:39:12 +02:00
Nassim Jahnke 4c75ea98f1 Update mapping files
Includes https://github.com/ViaVersion/Mappings/commit/c933b2799c6ad68be4977330899d5d3f3ab140e8 and https://github.com/ViaVersion/Mappings/commit/feed902814fc7c450a93015e44db549c0f15c551
2026-04-18 13:36:48 +02:00
Niko 5194c27e4c Fix skull owner with multiple properties of the same key in 1.20.5->1.20.3 (#1248) 2026-04-17 22:34:54 +02:00
Nassim Jahnke c887ab740b Improve 1.12 keep_alive handling
Fixes handling of batches of keep alives and the technically possible collisions
2026-04-16 16:51:56 +02:00
Jobs 63afb2d063 Fix inventory desync for <1.17 clients on 1.17+ servers (#1243) 2026-04-10 15:19:56 +02:00
riku6460 827c00f625 Fix set_beacon packet handling in 1.19->1.18.2 (#1241) 2026-04-07 20:44:59 +02:00
Glitch 8c07e58d40 Fix NPE in dimension_type registry handler in 26.1->1.21.11 (#1242) 2026-04-07 20:30:07 +02:00
Nassim Jahnke 3b30aa2454 Make entity data type mapping less manual 2026-04-06 13:45:49 +02:00
Nassim Jahnke 74b0bfb5ab Fix spectator interact in 26.1->1.21.11 2026-04-05 18:46:54 +02:00
Nassim Jahnke 757db4f25b Update VV usage 2026-04-02 15:13:01 +02:00
mfishmaandNassim Jahnke 51f061bfc1 Pass original item ids to custom model data (#1217)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-04-02 12:02:02 +02:00
Nassim Jahnke 14b3296959 Call super instead of mapTypes in entity rewriter 2026-04-01 17:26:14 +02:00
Florian Reuth 22e823e919 Directly override handle click event in 1.21.6->1.21.5 (#1233) 2026-04-01 10:07:38 +02:00
Nassim Jahnke bd3877bb46 Fix 1.21.6->1.21.5 show dialog read types 2026-03-31 10:53:35 +02:00
Nassim Jahnke 368881055d Fix non-empty custom tag backup in 1.20.5->1.20.4
Fixes #1231
2026-03-31 10:47:36 +02:00
Nassim Jahnke be0f50ad69 Default rewriter registrations across protocols 2026-03-30 20:38:54 +02:00
Nassim Jahnke b63f50750d 5.8.1 Release 2026-03-30 20:28:19 +02:00
Nassim Jahnke 50e7c15db1 Fix wolf_variant tracking in 1.21.5->1.21.4 2026-03-30 20:18:36 +02:00
Nassim Jahnke ef004cfa9c Fix blocks_attack backup with null bypass tag
Closes #1228
2026-03-29 15:18:15 +02:00
Nassim Jahnke 4f4fd5db8f Handle show dialog item changes
Fixes #1200
2026-03-28 17:11:14 +01:00
Nassim Jahnke 57157fd521 Bump version to 5.8.1-SNAPSHOT 2026-03-28 17:06:18 +01:00
Nassim Jahnke db8d9ab411 5.8.0 Release 2026-03-27 17:36:24 +01:00
Colbster937 f92a47df21 Map glazed terracotta blocks to their colored counterparts in 1.12->1.11 (#1220) 2026-03-27 17:36:07 +01:00
mfishma 00a08e95ef Add more sound mappings 2026-03-23 11:11:51 +01:00
Nassim Jahnke 1c652f82fc Remove dye data component too 2026-03-19 20:26:15 +01:00
Nassim Jahnke 7bb2c3e188 Add empty tags for older versions 2026-03-13 12:30:40 +01:00
Florian Reuth 92bbec9b73 Use new fallback value for object components if present in 1.21.9->1.21.7
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-03-12 21:10:50 +01:00
Nassim Jahnke 2604f8e37f Drop double interact 2026-03-11 21:40:01 +01:00
Nassim Jahnke 938164f22d 26.1-pre1 2026-03-10 21:30:08 +01:00
Nassim Jahnke 2b6948cec3 Fix entity data indexes 2026-03-07 09:49:04 +01:00
Nassim Jahnke 9cfa44368a Back up new item data 2026-03-06 21:15:25 +01:00
Nassim Jahnke f86925d747 26.1-snapshot-11 2026-03-06 20:57:59 +01:00
Nassim Jahnke 5a89919058 26.1-snapshot-10 2026-03-03 16:45:57 +01:00
Nassim Jahnke bf41b02718 26.1-snapshot-8 (maybe) 2026-03-03 16:45:57 +01:00
Nassim Jahnke 593106ff79 26.1-snapshot-7 2026-03-03 16:45:57 +01:00
Nassim Jahnke 0add20f841 26.1-snapshot-6 2026-03-03 16:45:57 +01:00
Nassim Jahnke dc521d9918 26.1-snapshot-5 2026-03-03 16:45:57 +01:00
Nassim Jahnke 98c20752c3 26.1-snapshot-4 2026-03-03 16:45:57 +01:00
Nassim Jahnke bbd17ea7c8 Fix day time setting 2026-03-03 16:45:57 +01:00
Nassim Jahnke b2902561bb 26.1-snapshot-3 2026-03-03 16:45:56 +01:00
Nassim Jahnke 010fc0bb13 26.1-snapshot-2 2026-03-03 16:45:56 +01:00
Nassim Jahnke d1a13c6f78 Update template protocol 2026-03-03 16:45:56 +01:00
Nassim Jahnke 7be2b232d1 26.1-snapshot-1 2026-03-03 16:45:55 +01:00
Nassim Jahnke 07baf2d068 5.7.2 Release 2026-03-01 16:37:00 +01:00
Nassim Jahnke 53a45d6ab6 [ci skip] Add gradle to dependabot config 2026-02-20 22:17:57 +01:00
Nassim Jahnke 831da784e6 Handle 1.21.11->1.21.9 biome sounds and particles 2026-02-20 13:56:30 +01:00
Florian Reuth 69620f894b [ci skip] Update my donation URL (#1198) 2026-02-05 17:09:24 +01:00
dependabot[bot] e5be7a8260 [ci skip] Bump actions/checkout from 6.0.1 to 6.0.2 (#1196)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 14:08:24 +01:00
dependabot[bot] a20f6db968 [ci skip] Bump actions/setup-java from 5.1.0 to 5.2.0 (#1197)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 14:08:10 +01:00
Nassim Jahnke a5949b9d4b [ci skip] Update supported Velocity versions 2026-01-31 12:05:07 +01:00
FlorianMichael e433fb3066 Add config option for code of conduct emulation in 1.21.9->1.21.7 (#1194) 2026-01-28 17:16:23 +01:00
Nassim Jahnke f3be21ed9d Fix trusted tag limiting
Fixes ViaVersion/ViaVersion#4792
2026-01-25 13:16:36 +01:00
FlorianMichael 2a2150beed [ci skip] Remove Gradle wrapper update action (#1192) 2026-01-24 19:25:46 +01:00
Nassim Jahnke f3af5f189c 5.7.1 Release 2026-01-18 16:06:36 +01:00
Pantera (Mad_Daniel) ca69def762 Fix missing entity data for pig and strider saddles in 1.21.5 -> 1.21.4 (#1182) 2026-01-17 17:57:33 +01:00
Pantera (Mad_Daniel) b268342acd Fix frog and cat variant mapping in 1.21.5->1.21.4 (#1183) 2026-01-17 17:54:41 +01:00
FlorianMichael bb61f4dece Add default impl class (#1184) 2026-01-17 14:42:47 +01:00
Nassim Jahnke 2360ea2c6b Fix 1.19->1.18 painting offsets
Fixes #964
2026-01-16 14:27:58 +01:00
Nassim Jahnke 44819eaf03 Move block entity handling to block rewriter
Also fixes double handling in 1.21.5->1.21.4
2026-01-10 13:11:15 +01:00
tmpod a839cb0684 Handle text components in signs in 1.21.7→1.21.5 (#1173) 2026-01-10 11:25:59 +01:00
FlorianMichaelandItsClairton b243e5ee32 Add missing warped & crimson sign range (#1179)
Co-authored-by: ItsClairton <hi@clairton.dev>
2026-01-10 10:23:53 +01:00
dewgs ab20f50510 Fix short overflow in old velocity handling (#1171) 2026-01-07 17:27:12 +01:00
FlorianMichaelandNassim Jahnke 1f4f45195c Update deps (#1170)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-01-07 16:57:38 +01:00
Nassim Jahnke 9e200b092b Prevent block breaking with spears
Closes #1169
2026-01-05 12:24:20 +01:00
Nassim Jahnke 16b057ecee [ci skip] Update copyright header 2026-01-04 15:43:11 +01:00
MelonHell a1f7c804c3 Don't require config impl class in ViaBackwardsPlatform#init (#1168) 2026-01-04 12:06:31 +01:00
Owen af9edc87fb Fix some older client issues for mannequins (#1166)
Resend the player head rotation, as older clients need to have the player head rotation sent as they don't handle the head rotation correctly in the spawn packet
2026-01-02 10:46:19 +01:00
booky fea7604ab1 Don't send nautilus mob effect to players < 1.21.11 (#1165) 2026-01-02 10:32:39 +01:00
Nassim Jahnke aeb0f4a7ee Bump version to 5.7.1-SNAPSHOT 2026-01-02 10:32:09 +01:00
Nassim Jahnke 76b98eb396 5.7.0 Release 2025-12-29 12:48:01 +01:00
Nassim Jahnke b33221b95c Don't throw on bad entity data in 1.14->1.13 2025-12-28 10:33:03 +01:00
Nassim Jahnke 8ce26b1353 Bump to 5.7.0-SNAPSHOT and update VV usage 2025-12-26 21:57:06 +01:00
9a79f9e217 Delay mannequin spawning for proper skin application (#1158)
Co-authored-by: FlorianMichael <git@florianmichael.de>
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2025-12-26 21:50:10 +01:00
Nassim Jahnke 44476f2468 Replace toIntExact with clamp
Fixes #1159
2025-12-25 09:10:09 +01:00
David Lüdtke 54655e34e7 Fix world border lerp size set in ticks instead of millis (#1156) 2025-12-23 09:55:03 +01:00
Nassim Jahnke 863258df4e Correct overworld fog color 2025-12-21 16:55:01 +01:00
Nassim Jahnke 8a5fce2d2e Put set_objective and set_score packets through component rewriter
Fixes #1155
2025-12-21 15:53:03 +01:00
Nassim Jahnke 5374c3b626 Fix avatar arm handling in 1.21.11->1.21.9 2025-12-20 22:53:24 +01:00
FlorianMichael 96e0d85bc0 Map pale oak shelf to pale oak planks in 1.21.9->1.21.7 (#1154) 2025-12-20 16:38:29 +01:00
Kichura 84576d1d95 [ci skip] Set CI timeout to 30 mins (#1153) 2025-12-20 15:46:05 +01:00
Nassim Jahnke c6f0717ad5 Convert compact sound list to single entry in registry data 2025-12-20 12:00:16 +01:00
Nassim Jahnke 395bebac62 Remove tamable entity data from nautilus
Fixes #1152
2025-12-14 09:25:07 +01:00
FlorianMichael 6d19ad3b81 [ci skip] Include the newest ViaProxy version from 3.0.0 to 4.0.0 (#1151) 2025-12-13 19:59:23 +01:00
Nassim Jahnke 38080fc5cc Remove 1.21.11 registries 2025-12-13 12:04:12 +01:00
FlorianMichael 285dcdd81f Add ViaBackwardsPlatform#init with config instance (#1149) 2025-12-13 11:30:04 +01:00
Nassim Jahnke 1f5fd88fef 5.6.0 Release 2025-12-12 16:00:57 +01:00
Nassim Jahnke 531f7d078e Remove nautilus variant in 1.21.11 component rewriter 2025-12-12 16:00:57 +01:00
Nassim Jahnke 2806671813 Add translatables 2025-12-12 16:00:56 +01:00
Nassim Jahnke 7634a7ec7a Add fog effects to dimensions and biomes 2025-12-12 16:00:56 +01:00
Nassim Jahnke 8cd5bd3368 1.21.11-pre4 2025-12-12 16:00:56 +01:00
Nassim Jahnke 0735e4afb5 Handle biome color type changes 2025-12-12 16:00:56 +01:00
Nassim Jahnke 3568eee8f2 Back up new item data 2025-12-12 16:00:55 +01:00
Nassim Jahnke e694b3532a 1.21.11-pre1 2025-12-12 16:00:55 +01:00
Nassim Jahnke 2bcf79c501 25w46a 2025-12-12 16:00:55 +01:00
Nassim Jahnke 7ded34c55e 25w45a 2025-12-12 16:00:55 +01:00
Nassim Jahnke 3bdeed8a9f 25w43a 2025-12-12 16:00:54 +01:00
Nassim Jahnke 30df707369 WIP 25w42a 2025-12-12 16:00:54 +01:00
github-actions[bot]andgradle-update-robot cf8058016c Update Gradle Wrapper from 9.2.0 to 9.2.1 (#1141)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-12-12 15:58:35 +01:00
Kichura 3468b0a785 Update workflow configs (#1144) 2025-12-06 20:34:00 +01:00
tmpod d273b06e05 Fix text components in signs not being rewritten in 1.21.9→1.21.7 (#1147) 2025-12-06 20:14:36 +01:00
dependabot[bot] 4f561ba4a7 Bump actions/checkout from 5 to 6 (#1142)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 21:58:08 +01:00
Nanashi.andFlorianMichael 0a5035d209 More dialog emulation fixes (#1131)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-11-24 21:57:46 +01:00
Nassim Jahnke 609b657c68 Handle set_player_team text component changes 2025-11-23 19:47:05 +01:00
Nassim Jahnke 5885074fcd [ci skip] Update issue template 2025-11-18 19:50:03 +01:00
Nassim Jahnke d499918e4b Don't cancel full equipment containing saddle in 1.21.5->1.21.4
Plugins manually sending equipment packets may include saddles for entities that shouldn't have saddle equipment, though the client will ignore them
Closes #1140
2025-11-18 19:33:34 +01:00
FlorianMichael 17d7b4873f Set accepted = true in 1.12->1.11.1 shift click fix (#1139) 2025-11-16 19:04:17 +01:00
FlorianMichael 38243bad78 [ci skip] Update ViaFabricPlus jars path (#1133) 2025-11-12 16:58:40 +01:00
Nassim Jahnke 50577abbb5 Fix jukebox_playable backup
Fixes #1130
2025-11-08 10:45:51 +01:00
github-actions[bot]andgradle-update-robot 277de42948 Update Gradle Wrapper from 9.1.0 to 9.2.0 (#1129)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-11-03 16:52:13 +01:00
FlorianMichael 4c26915fdf Fix text display y offset in 1.19.4->1.19.3 (#1128) 2025-11-01 15:07:36 +01:00
FlorianMichael 7c98b75543 Cancel sign editor open packet for invalid positions in 1.21.2->1.21 (#1099) 2025-11-01 14:59:13 +01:00
Nassim Jahnke 7d39bcc365 Fix regression in cancelling new 1.21.5 registries 2025-10-28 21:11:26 +01:00
Nassim Jahnke 85688beba8 Go through normal registry handling for removed registries in 1.21.5->1.21.4 2025-10-20 14:28:26 +02:00
FlorianMichael fd16c4469c Add option to disable dialog handling in 1.21.6->1.21.5 (#1116) 2025-10-18 18:34:23 +02:00
Nassim Jahnke a37605e920 Update VV usage 2025-10-14 17:59:53 +02:00
FlorianMichael 1d4e41f867 Fix custom action button in notice dialogs not added in 1.21.6->1.21.5 (#1117) 2025-10-13 20:30:47 +02:00
Nassim Jahnke 1f4acbbc60 5.5.1 Release 2025-10-12 18:43:52 +02:00
Nassim Jahnke eff547019c Remove instrument and jukebox playable in show_item hovers in 1.21.5->1.21.4 2025-10-12 18:43:17 +02:00
Nassim Jahnke bbb52f575a Add --refresh-dependencies to publish workflow 2025-10-07 16:14:10 +02:00
Nassim Jahnke 74ad2d15fb Update VV usage again 2025-10-07 15:39:19 +02:00
Nassim Jahnke 024fe774f4 Update VV usage 2025-10-07 15:26:05 +02:00
dependabot[bot] 0df9c50251 Bump gradle/actions from 4 to 5 (#1115)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 23:37:26 +02:00
Nassim Jahnke e8637e5753 Update sound mapping format
VV now includes full sound name mappings, so VB can map them via registry indexes and doesn't need the extra sound file anymore
2025-10-06 20:44:10 +02:00
Nassim Jahnke 64b454de6f Fix world border scale in 1.21.9->1.21.7 2025-10-05 22:20:44 +02:00
FlorianMichael 433f46e34e Handle DEBUG_SAMPLE_SUBSCRIPTION structure change in 1.21.9 ->1.21.7 (#1111) 2025-10-05 08:49:11 +02:00
Nassim Jahnke fbe6a67750 Fix inverted hidden components checks in 1.21.5->1.21.4
Fixes #1110
2025-10-04 11:02:49 +02:00
Nassim Jahnke 454e97c844 Don't remove font
Closes #1109
2025-10-04 10:08:01 +02:00
FlorianMichael fccea9b55d Throw out object components in 1.21.9->1.21.7 (#1108) 2025-10-03 21:42:31 +02:00
Nassim Jahnke 917427c940 5.5.0 Release 2025-10-03 13:48:04 +02:00
Nassim Jahnke b7ddc108f5 Prepare for the release later 2025-10-03 08:18:06 +02:00
FlorianMichael db65302112 Write empty tag if no shoulder data is present 2025-10-02 18:13:42 +02:00
FlorianMichael 795b195690 Use translation keys for code of conduct dialog 2025-10-02 14:25:23 +02:00
Nassim Jahnke b7c42f9b2e Cancel mannequin data from unknown entities 2025-09-30 18:29:04 +02:00
Nassim Jahnke 1a0c79c46a Add 1.21.9 translations 2025-09-30 18:05:04 +02:00
Nassim Jahnke 95d809f53a Update item_model use 2025-09-30 14:37:36 +02:00
FlorianMichael f8c249f2c2 Only register open screen translatable rewriter 2025-09-26 20:41:01 +02:00
FlorianMichael fe890fa59e Handle relative player rotations 2025-09-25 17:03:31 +02:00
Nassim Jahnke 9806afed99 Handle SET_DEFAULT_SPAW_POSITION change 2025-09-25 16:59:57 +02:00
Nassim Jahnke 432c669daf 1.21.9-pre1 2025-09-25 16:59:57 +02:00
Nassim Jahnke 838d83897b Start emulating mannequins via players 2025-09-25 16:59:57 +02:00
Nassim Jahnke e10c73138d 25w37a 2025-09-25 16:59:57 +02:00
FlorianMichael e0892faf13 Show server code of conduct as dialog screen 2025-09-25 16:59:57 +02:00
Nassim Jahnke c03cb66bbd wip 25w36a/b 2025-09-25 16:59:56 +02:00
Nassim Jahnke ea1d86642e 25w35a 2025-09-25 16:59:56 +02:00
Nassim Jahnke 6c9c7288c4 25w34b 2025-09-25 16:59:56 +02:00
Nassim Jahnke 8dab7f7284 25w33a 2025-09-25 16:59:56 +02:00
Nassim Jahnke f0c16003e0 25w32a 2025-09-25 16:59:56 +02:00
Nassim Jahnke 4d4b18b80e 25w31a 2025-09-25 16:59:56 +02:00
Nassim Jahnke 99abab0d62 Update dependencies 2025-09-20 22:39:48 +02:00
EnZaXD f7656fb45f Always remap show_dialog/custom click events (#1104) 2025-09-18 20:03:13 +02:00
EnZaXD 6a440aaeda Handle signed chat commands as well for custom click events (#1103) 2025-09-18 20:02:42 +02:00
EnZaXD 075ca7044d Make some functions protected in ChestDialogViewProvider (#1101) 2025-09-16 21:31:56 +02:00
EnZaXD a8cd653a7a Remove serialize versions from item hasher (#1102) 2025-09-16 21:31:51 +02:00
EnZaXD 191dd24117 Add missing sound name handlers for biomes (#1098) 2025-09-13 10:08:02 +02:00
EnZaXD 6ad05d8bc2 Null check chest dialog storage in ChestDialogViewProvider#closeDialog (#1097) 2025-09-12 21:14:54 +02:00
Nassim Jahnke c5a2a6ae6e Reset player position storage on respawn 2025-09-03 17:11:41 +02:00
EnZaXD 31f7f4edc1 Rename ProtocolRunnable, always submit tick logic into event loop (#1093) 2025-09-03 17:08:08 +02:00
purpurcof b2a2712949 Fix reading any NBT type for SERVER_LINKS (#1092) 2025-09-01 17:31:05 +02:00
EnZaXD 7bd6a849a3 Fix SOUND_ENTITY remap not working for the player in 1.14->1.13.2 (#1086) 2025-09-01 16:30:33 +02:00
riku6460 473b4af0d0 Add missing check whether the player is set in client tick emulation 1.21.2->1.21 (#1090) 2025-08-29 17:16:07 +02:00
dependabot[bot] b7c8891497 Bump actions/setup-java from 4 to 5 (#1089)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 15:36:00 +02:00
Nassim Jahnke be5344b3e4 Reassign item on handleItemToClient calls
Needed in rewriters before 1.20 with a recent change; the rest weren't technically necessary
2025-08-22 20:10:10 +02:00
Nassim Jahnke cc4ea71722 Fix custom name in banners etc. in 1.21.5->1.21.4 2025-08-17 16:37:16 +02:00
EnZaXD f288f2d716 Add dialog styling options (#1072) 2025-08-17 08:16:42 +02:00
dependabot[bot] 61a4cead72 [ci skip] Bump actions/checkout from 4 to 5 (#1080)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 08:22:46 +02:00
EnZaXDandNassim Jahnke b9ead8109f [ci skip] Gradle & Shadow 9.0.0; Rewrite .gitignore file (#1075)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2025-08-09 14:17:40 +02:00
EnZaXD 12cde18a3d Use ViaBackwardsPlatform#getLogger for protocol logger creation (#1078) 2025-08-08 16:03:40 +02:00
EnZaXD b8adbde876 Add statistic mappings for 1.21.6->1.21.5 (#1077) 2025-08-03 09:34:06 +02:00
EnZaXD 6faf407cc9 Use SerializerVersion.V1_21_6 in 1.21.6->1.21.5 (#1073) 2025-07-31 13:05:01 +02:00
EnZaXD f3f19dfd4e Pass dialog title through component conversion in 1.21.6->.5 (#1074) 2025-07-31 13:04:53 +02:00
EnZaXD 80ed7e1e75 Handle HIDE_ADDITIONAL_TOOLTIP in chat items in 1.21.5->1.21.4 (#1068) 2025-07-31 13:04:42 +02:00
Nassim Jahnke 6363cd38ab 5.4.2 Release 2025-07-23 18:41:56 +02:00
Nassim Jahnke 5ca359b287 Fix hidden tooltip in emulated dialog item widgets 2025-07-23 18:38:07 +02:00
Nassim Jahnke c18c670bdb Fix 1.10->1.9 potion entity data 2025-07-22 00:04:13 +02:00
Nassim Jahnke 345406ecae Back up custom attribute modifier ids 2025-07-18 11:06:44 +02:00
Nassim Jahnke 4a159bf16a [ci skip] Split up publishing steps
Putting them into the same step meant if one publish action failed, the second one wouldn't run. Before this change, Modrinth would often block Hangar from publishing
2025-07-17 16:10:46 +02:00
Pantera (Mad_Daniel) 6a2482f42f Fix ADD_ENTITY velocity for non-living entities on 1.21.6+ servers (#1066) 2025-07-15 15:28:43 +02:00
Pantera (Mad_Daniel) 8075d49ad2 Fix sendUnlockedRecipes (#1067) 2025-07-14 22:31:14 +02:00
Nassim Jahnke 36aecf3444 [ci skip] Clean up imports 2025-07-14 12:42:13 +02:00
Nassim Jahnke f0aa7d9dae Fix minecarts losing type in 1.21.5->1.21.4
Fixes #1057
2025-07-13 09:31:04 +02:00
Nassim Jahnke b63e031662 [ci skip] Remove clearOnServerSwitch overrides 2025-07-12 10:37:06 +02:00
EnZaXD 8825ef0f44 [ci skip] Add Java resolving plugin (#1059) 2025-07-12 10:28:37 +02:00
Pantera (Mad_Daniel) eea2687e66 Add limit (#1063) 2025-07-11 10:18:46 +02:00
EnZaXD 712f656a3a Remap UI sound source to master in 1.21.6->1.21.5 (#1056) 2025-07-06 21:17:58 +02:00
Nassim Jahnke 181a0cb7c1 Cache parsed item name and lore in older protocols 2025-07-05 13:04:55 +02:00
Nassim Jahnke b367037cef Bump version to 5.4.2-SNAPSHOT 2025-07-04 13:37:59 +02:00
Nassim Jahnke b90b573f1d 5.4.1 Release 2025-06-30 16:04:55 +02:00
Nassim Jahnke 74aeadd688 1.21.7-rc1/2 2025-06-30 16:04:53 +02:00
riku6460 6f27988cf6 Ensure run_command click events start with '/' in 1.21.5->1.21.4 (#1051) 2025-06-30 16:03:42 +02:00
Nassim Jahnke 81aad86d9f Map waterlogged light to water
Fixes #1038
2025-06-30 12:32:05 +02:00
FlorianMichael 1e7dbf38fd [ci skip] Add SECURITY.md (#1031) 2025-06-29 15:37:05 +02:00
riku6460andFlorianMichael 0404184e15 Use correct tag type to write custom click actions in 1.21.6->.5 (#1050)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-06-29 09:45:13 +02:00
FlorianMichael 64a7d9f8bd Strip default namespace when reading types (#1049) 2025-06-28 13:06:10 +02:00
FlorianMichael 924346882c Fix style and remap translations for item description in 1.21.6->.5 dialogs (#1048) 2025-06-28 12:34:32 +02:00
FlorianMichael 1d7332101f Fix run_command and custom click events (#1046) 2025-06-25 09:08:45 +02:00
FlorianMichael 30e63ebc3b Improve multiple text widgets follow one another in dialogs (#1044) 2025-06-24 13:36:19 +02:00
FlorianMichael 217c9459f5 Emulate dialog screens using chest inventories (#1041) 2025-06-23 22:53:59 +02:00
Nassim Jahnke ead2c6f330 Send sneaking command on vehicle exit in 1.21.2->1.21.1
Fixes #1001
2025-06-23 12:26:04 +02:00
Nassim Jahnke 1a972da613 Fix horse saddle handling in 1.21.5->1.21.4 2025-06-23 11:10:47 +02:00
Nassim Jahnke 44dbbf37e2 Remove saddle slot group from enchantments in 1.21.5->1.21.4
Fixes #1033
2025-06-22 22:14:47 +02:00
RK_01 def010c2bf Remap difficulty data type (#1040) 2025-06-21 10:08:55 +02:00
Nassim Jahnke 75744d5525 Bump version to 5.4.1-SNAPSHOT 2025-06-21 09:46:31 +02:00
Nassim Jahnke 7f66786b76 5.4.0 Release 2025-06-20 19:07:34 +02:00
Nassim Jahnke 6993308019 Remove hanging entity direction 2025-06-17 17:28:56 +02:00
Nassim Jahnke a69b0b499c Add translations 2025-06-17 02:12:47 +02:00
Nassim Jahnke a48731ded2 1.21.6-pre1 2025-06-17 02:11:22 +02:00
Nassim Jahnke 11857f1abe 25w21a 2025-06-17 02:11:22 +02:00
Nassim Jahnke fdf2d5e87b Use updated versioned types 2025-06-17 02:11:22 +02:00
Nassim Jahnke 069c537dbb 25w20a 2025-06-17 02:11:22 +02:00
Nassim Jahnke 22e86fb127 Add hashed item handling 2025-06-17 02:11:22 +02:00
Nassim Jahnke d08da420b2 Fix modifier display backup handling 2025-06-17 02:11:22 +02:00
Nassim Jahnke 5bddf285e3 25w19a 2025-06-17 02:11:22 +02:00
Nassim Jahnke 3ba77829fe Shift player_command actions 2025-06-17 02:11:22 +02:00
Nassim Jahnke 3c3cd07fd7 25w16a 2025-06-17 02:11:21 +02:00
Nassim Jahnke 5a2d3b6b31 25w15a 2025-06-17 02:11:21 +02:00
FlorianMichael 0c21ddfe40 Add missing dimension change checks for entity tracking (#1034) 2025-06-17 02:11:05 +02:00
FlorianMichael 9b65b59411 Push block entity custom name through component conversion in 1.20.3->.2 (#1035) 2025-06-15 04:44:23 +02:00
riku6460 d3248037d8 Don't show enchantment level if level == 1 && max_level == 1 (#1027) 2025-06-12 15:10:20 +02:00
FlorianMichael e0f3a98d79 Don't add block mappings for alternative mappings (#1024) 2025-06-12 15:10:11 +02:00
Nassim Jahnke 39a4d4e973 Make publish action manually runnable 2025-06-11 10:38:45 +02:00
FlorianMichael 8a9bf708f2 Add option to disable display entity emulation in 1.19.4->.3 (#1022) 2025-05-31 02:43:19 +02:00
Nassim Jahnke 5070e51b04 Update VV usage 2025-05-27 14:28:31 +02:00
riku6460 12baac5cbd Fix login finished packet in 1.19->1.18.2 (#1018) 2025-05-27 04:41:00 +02:00
Nassim Jahnke 8669c17512 Update VV usage 2025-05-26 11:57:18 +02:00
github-actions[bot]andgradle-update-robot fe993fc2a7 Update Gradle Wrapper from 8.14 to 8.14.1 (#1016)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-05-22 17:35:16 +02:00
AdrianandFlorianMichael 54af45da27 Add alternative scaffolding mapping in 1.14->1.13.2 (#1015)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-05-22 15:18:40 +02:00
Nassim Jahnke 175daef7da Refactor 1.20.5+ versioned types 2025-05-17 14:30:10 +02:00
Nassim Jahnke 986ecaaf8d Fix 1.20.5 item handler
Fixes #1011
2025-05-15 15:10:50 +02:00
Nassim Jahnke b42c19752c Remove no longer needed container handling, now handled in the super call 2025-05-15 11:10:23 +02:00
Nassim Jahnke d98de382fc Update VV usage 2025-05-14 14:00:00 +02:00
Nassim Jahnke 13bc18b496 Update VV usage 2025-05-13 22:56:18 +02:00
Nassim Jahnke 4160b37f13 Update VV usage 2025-05-12 19:08:05 +02:00
FlorianMichael f9f7a24dda [ci skip] Make the runViaProxy task work with Gradle's configuration cache (#1005) 2025-05-12 17:54:17 +02:00
FlorianMichael 21fd034c02 Remove enchantments with level 0 if sent by the client in 1.21.2->1.21 (#1004) 2025-05-12 15:31:37 +02:00
Nassim Jahnke 6a59e887c8 Attempt to convert serverbound clicks to hashed items in 1.21.5
This will fix desyncs on item drags due to the server missing the individual data hashes. Some are not implemented, in which case it will still cause those sames issues, but generally this will fix its handling for most items
2025-05-11 23:14:51 +02:00
FlorianMichael 32488cf2ff [ci skip] Allow build if Git is not installed or the project is downloaded as code zip (#1002) 2025-05-11 22:26:49 +02:00
FlorianMichael 774a35db17 [ci skip] Don't publish viaversion-fabric to the repository server (#1000) 2025-05-05 21:07:22 +02:00
FlorianMichael 32f41382fa Add missing PLAYER_CHAT handlers in 1.20/1.21 versions (#999) 2025-04-28 22:08:25 +02:00
Nassim Jahnke c9573a1cfd Move data handling 1.21.5 text component rewriting to the right place
Fixes #997
2025-04-28 16:20:06 +02:00
github-actions[bot]andgradle-update-robot def9df84b4 Update Gradle Wrapper from 8.13 to 8.14 (#996)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-04-26 20:51:11 +02:00
FlorianMichael fd4bc59058 Fix potion entity hover event in 1.21.5->1.21.4 (#995) 2025-04-26 20:50:21 +02:00
399 changed files with 15831 additions and 5604 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
@../AGENTS.md
+1 -1
View File
@@ -1,3 +1,3 @@
github: kennytv
patreon: kennytv
custom: ['https://florianmichael.de/donate']
custom: ['https://florianreuth.de/donate']
+2 -11
View File
@@ -48,21 +48,12 @@ body:
label: Steps to Reproduce
description: |
List the steps on how we can reproduce the issue. Make sure we can easily understand what you mean with each step.
**Please always include the client version(s) with which the issue happens. Ideally also try to find out from what specific version downward/in what version range the issue happens.**
placeholder: |
Example:
1. Login with a 1.16.5 client
2. Place a sign
3. The sign text is displayed wrong
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: |
Describe what exactly you expected to happen.
placeholder: |
Example: "Placed sign text should not disappear."
3. The sign text disappears
validations:
required: true
+12 -1
View File
@@ -1,6 +1,17 @@
version: 2
# Disabled for the time being, being done manually instead
updates:
- package-ecosystem: "github-actions"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "weekly"
interval: "monthly"
open-pull-requests-limit: 0
- package-ecosystem: "gradle"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 0
+12 -8
View File
@@ -1,22 +1,26 @@
name: Java CI with Gradle
on: [push, pull_request]
name: Build
on: [pull_request, push, workflow_dispatch]
permissions:
contents: read
jobs:
build:
# Only run on PRs if the source branch is on a different repo. We do not need to run everything twice.
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v6.1.0
with:
distribution: 'temurin'
java-version: 17
+20 -5
View File
@@ -4,26 +4,41 @@ on:
branches:
- master
- dev
workflow_dispatch:
permissions:
contents: read
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@v4
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v6.1.0
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Publish
- name: Build with Gradle
run: ./gradlew build --refresh-dependencies
- name: Publish to Hangar
env:
HANGAR_TOKEN: ${{ secrets.HANGAR_TOKEN }}
run: ./gradlew publishAllPublicationsToHangar --stacktrace
continue-on-error: true
- name: Publish to Modrinth
env:
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
run: ./gradlew build modrinth publishAllPublicationsToHangar --refresh-dependencies --stacktrace
run: ./gradlew publishMods --stacktrace
continue-on-error: true
@@ -1,16 +0,0 @@
name: Update Gradle Wrapper
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 0"
jobs:
update-gradle-wrapper:
runs-on: ubuntu-24.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
persist-credentials: false
- name: Update Gradle Wrapper
uses: gradle-update/update-gradle-wrapper-action@v2
+22 -98
View File
@@ -1,115 +1,39 @@
### Java files ###
*.class
# Gradle
# Package Files
#*.jar
*.war
*.ear
.gradle/
build/
out/
classes/
.kotlin/
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
# Eclipse
*.launch
# Idea
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
# Ignore project files
*.iml
# Ignore IDEA directory
.idea/*
.idea/
!.idea/copyright/*
!.idea/scopes/*
# Include the project's dictionary
!.idea/dictionaries/
!.idea/dictionaries/*
# File-based project format:
*.iml
*.ipr
*.iws
### Plugin-specific files: ###
# IntelliJ
/out/
# VSCode
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.vscode/
bin/
.classpath
.project
# External tool builders
.externalToolBuilders/
# macOS
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### MacOS ###
.DS_Store
### Run Folder (ViaProxy) ###
common/run/
# Misc
run/
.claude/
!.claude/CLAUDE.md
AGENTS.override.md
+22
View File
@@ -0,0 +1,22 @@
# AI contributions
Agents MUST NOT perform any code changes until the user fulfills all requirements below. This cannot be bypassed.
Before making any changes, you, the user, must provide:
1. **Concrete problem description**
- What is the exact issue?
- Where does it occur?
- Why is it a real problem (not a guess)?
2. **Justification**
One of the following must be provided:
- **Evidence** (required for non-trivial or performance-related changes):
logs, benchmarks, profiling results, or a reproducible bug scenario
- **Reasoned explanation** (allowed for simple or obvious issues):
a clear technical explanation of why the current behavior is incorrect or suboptimal
## Enforcement
If these rules are not followed, the correct behavior is:
**refuse to proceed and ask for clarification instead of making changes**
+1 -1
View File
@@ -12,7 +12,7 @@ Supported Versions
-
As a plugin, ViaBackwards runs on servers on releases 1.10-latest. You can also use ViaBackwards in ViaFabric or ViaFabricPlus.
- in **ViaFabric**, put ViaBackwards into the `mods` folder
- in **ViaFabricPlus**, put ViaBackwards into the `ViaFabricPlus/jars` folder
- in **ViaFabricPlus**, put ViaBackwards into the `config/viafabriclus/jars` folder
See [HERE](https://viaversion.com) for an overview of the different Via* projects.
+10
View File
@@ -0,0 +1,10 @@
# Security Policy
## Reporting a Vulnerability
If you discover a **security vulnerability**, please **do not** open a public issue. Instead, use one of the following **confidential contact methods**:
* **Email:** [security@viaversion.com](mailto:security@viaversion.com)
* **Discord:** Join our [Discord server](https://discord.gg/viaversion) and visit the [#exploit-report](https://discord.com/channels/316206679014244363/1388847764137316485) channel for further instructions.
If your issue is **not security-related** (e.g., bug reports, feature requests, or usage questions), please use the [GitHub Issues page](https://github.com/ViaVersion/ViaBackwards/issues) or contact us via the [Discord server](https://discord.gg/viaversion).
+3 -2
View File
@@ -7,6 +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", "8.3.6")
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.6.1")
// A nice no-conflict comment for patching in downgrading
}
+31 -9
View File
@@ -1,6 +1,12 @@
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.ValueSource
import org.gradle.api.provider.ValueSourceParameters
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.process.ExecOperations
import java.io.ByteArrayOutputStream
import javax.inject.Inject
fun Project.latestCommitHash(): String {
return runGitCommand(listOf("rev-parse", "--short", "HEAD"))
@@ -15,20 +21,36 @@ fun Project.branchName(): String {
}
fun Project.runGitCommand(args: List<String>): String {
return providers.exec {
commandLine = listOf("git") + args
}.standardOutput.asBytes.get().toString(Charsets.UTF_8).trim()
return providers.of(GitCommand::class.java) { parameters.args.set(args) }.getOrNull() ?: "unknown"
}
fun Project.parseMinecraftSnapshotVersion(version: String): String? {
val separatorIndex = version.indexOf('-')
val lastSeparatorIndex = version.lastIndexOf('-')
if (separatorIndex == -1 || separatorIndex == lastSeparatorIndex) {
return null
abstract class GitCommand : ValueSource<String, GitCommand.GitCommandParameters> {
@get:Inject
abstract val execOperations: ExecOperations
interface GitCommandParameters : ValueSourceParameters {
val args: ListProperty<String>
}
override fun obtain(): String? {
try {
val command = listOf("git") + parameters.args.get()
val output = ByteArrayOutputStream()
execOperations.exec {
commandLine = command
standardOutput = output
isIgnoreExitValue = true
}
return output.toString(Charsets.UTF_8).trim().takeIf { it.isNotBlank() }
} catch (e: Exception) {
return null
}
}
return version.substring(separatorIndex + 1, lastSeparatorIndex)
}
fun JavaPluginExtension.javaTarget(version: Int) {
toolchain.languageVersion.set(JavaLanguageVersion.of(version))
}
@@ -8,7 +8,7 @@ tasks {
val ver = project.version.toString()
val desc = project.description
filesMatching(listOf("plugin.yml", "META-INF/sponge_plugins.json", "fabric.mod.json")) {
expand("version" to ver, "description" to desc)
expand(mapOf("version" to ver, "description" to desc))
}
}
javadoc {
@@ -18,6 +18,7 @@ tasks {
compileJava {
options.encoding = Charsets.UTF_8.name()
options.compilerArgs.addAll(listOf("-nowarn", "-Xlint:-unchecked", "-Xlint:-deprecation"))
options.isFork = true
}
}
Whitespace-only changes.
@@ -14,6 +14,7 @@ tasks {
from(project.rootProject.file("LICENSE"))
}
val shadowJar = named<ShadowJar>("shadowJar") {
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
archiveClassifier.set("")
configureRelocations()
}
+3 -3
View File
@@ -1,6 +1,7 @@
plugins {
base
id("vb.build-logic")
id("vb.base-conventions") apply false
id("vb.shadow-conventions") apply false
}
allprojects {
@@ -13,8 +14,7 @@ val main = setOf(
projects.viabackwards,
projects.viabackwardsCommon,
projects.viabackwardsBukkit,
projects.viabackwardsVelocity,
projects.viabackwardsFabric
projects.viabackwardsVelocity
).map { it.path }
subprojects {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,11 +19,12 @@
package com.viaversion.viabackwards;
import com.viaversion.viabackwards.api.ViaBackwardsPlatform;
import com.viaversion.viabackwards.listener.BlockBreakListener;
import com.viaversion.viabackwards.listener.FireDamageListener;
import com.viaversion.viabackwards.listener.FireExtinguishListener;
import com.viaversion.viabackwards.listener.LecternInteractListener;
import com.viaversion.viabackwards.listener.PlayerItemDropListener;
import com.viaversion.viabackwards.listener.DurabilitySync1_11;
import com.viaversion.viabackwards.listener.PlayerHurtSound1_12;
import com.viaversion.viabackwards.listener.FireExtinguish1_16;
import com.viaversion.viabackwards.listener.LecternInteract1_14;
import com.viaversion.viabackwards.listener.ItemDropSync1_17;
import com.viaversion.viabackwards.listener.SpearAttack1_21_11;
import com.viaversion.viabackwards.protocol.v1_20_2to1_20.provider.AdvancementCriteriaProvider;
import com.viaversion.viabackwards.provider.BukkitAdvancementCriteriaProvider;
import com.viaversion.viaversion.api.Via;
@@ -53,20 +54,23 @@ public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
ViaBackwardsPlatform.super.enable();
final ProtocolVersion protocolVersion = Via.getAPI().getServerVersion().highestSupportedProtocolVersion();
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_21_11)) {
new SpearAttack1_21_11(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_17)) {
new PlayerItemDropListener(this).register();
new ItemDropSync1_17(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_16)) {
new FireExtinguishListener(this).register();
new FireExtinguish1_16(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_14)) {
new LecternInteractListener(this).register();
new LecternInteract1_14(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_12)) {
new FireDamageListener(this).register();
new PlayerHurtSound1_12(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_11)) {
new BlockBreakListener(this).register();
new DurabilitySync1_11(this).register();
}
final ViaProviders providers = Via.getManager().getProviders();
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,9 +27,9 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
public class BlockBreakListener extends ViaBukkitListener {
public class DurabilitySync1_11 extends ViaBukkitListener {
public BlockBreakListener(final BukkitPlugin plugin) {
public DurabilitySync1_11(final BukkitPlugin plugin) {
super(plugin, Protocol1_11To1_10.class);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,9 +28,9 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
public class FireExtinguishListener extends ViaBukkitListener {
public class FireExtinguish1_16 extends ViaBukkitListener {
public FireExtinguishListener(BukkitPlugin plugin) {
public FireExtinguish1_16(BukkitPlugin plugin) {
super(plugin, Protocol1_16To1_15_2.class);
}
@@ -1,7 +1,7 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,9 +27,9 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerDropItemEvent;
import org.bukkit.inventory.ItemStack;
public class PlayerItemDropListener extends ViaBukkitListener {
public class ItemDropSync1_17 extends ViaBukkitListener {
public PlayerItemDropListener(final BukkitPlugin plugin) {
public ItemDropSync1_17(final BukkitPlugin plugin) {
super(plugin, Protocol1_13_1To1_13.class); // Starts with 1.13 clients on 1.17 servers
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,9 +30,9 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
public class LecternInteractListener extends ViaBukkitListener {
public class LecternInteract1_14 extends ViaBukkitListener {
public LecternInteractListener(BukkitPlugin plugin) {
public LecternInteract1_14(BukkitPlugin plugin) {
super(plugin, Protocol1_14To1_13_2.class);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -28,9 +28,9 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageEvent;
public class FireDamageListener extends ViaBukkitListener {
public class PlayerHurtSound1_12 extends ViaBukkitListener {
public FireDamageListener(BukkitPlugin plugin) {
public PlayerHurtSound1_12(BukkitPlugin plugin) {
super(plugin, Protocol1_12To1_11_1.class);
}
@@ -0,0 +1,48 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.listener;
import com.viaversion.viabackwards.BukkitPlugin;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.Protocol1_21_11To1_21_9;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.inventory.ItemStack;
public class SpearAttack1_21_11 extends ViaBukkitListener {
public SpearAttack1_21_11(final BukkitPlugin plugin) {
super(plugin, Protocol1_21_11To1_21_9.class);
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void onBlockBreak(final BlockBreakEvent event) {
final Player player = event.getPlayer();
if (!isOnPipe(player)) {
return;
}
final ItemStack item = player.getInventory().getItemInMainHand();
if (item.getType().name().endsWith("_SPEAR")) {
// Prevent spears from breaking blocks
event.setCancelled(true);
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
+30 -19
View File
@@ -27,29 +27,40 @@ java {
// Task to quickly test/debug code changes using https://github.com/ViaVersion/ViaProxy
// For further instructions see the ViaProxy repository README
tasks.register<JavaExec>("runViaProxy") {
dependsOn(tasks.shadowJar)
val prepareViaProxyFiles = tasks.register<Copy>("prepareViaProxyFiles") {
description = "Prepares the ViaProxy run dir for the runViaProxy task"
dependsOn(project.tasks.shadowJar)
val viaProxyConfiguration = configurations.create("viaProxy")
viaProxyConfiguration.dependencies.add(dependencies.create(rootProject.libs.viaProxy.get().copy().setTransitive(false)))
from(project.tasks.shadowJar.map { it.archiveFile.get().asFile })
into(layout.projectDirectory.dir("run/jars"))
val projectName = project.name
rename { "${projectName}.jar" }
}
val cleanupViaProxyFiles = tasks.register<Delete>("cleanupViaProxyFiles") {
description = "Deletes ViaProxy logs and the compiled project jar from its jars dir"
delete(
layout.projectDirectory.file("run/jars/${project.name}.jar"),
layout.projectDirectory.dir("run/logs")
)
}
val viaProxyConfiguration: Configuration = configurations.create("viaProxyConfiguration") {
dependencies.add(rootProject.libs.viaProxy.get().copy().setTransitive(false))
}
tasks.register<JavaExec>("runViaProxy") {
description = "Runs ViaProxy locally"
dependsOn(prepareViaProxyFiles)
finalizedBy(cleanupViaProxyFiles)
mainClass.set("net.raphimc.viaproxy.ViaProxy")
classpath = viaProxyConfiguration
workingDir = file("run")
jvmArgs = listOf("-DskipUpdateCheck")
workingDir = layout.projectDirectory.dir("run").asFile
jvmArgs = listOf("-DskipUpdateCheck", "-Dviaproxy.gui.autoStart")
if (System.getProperty("viaproxy.gui.autoStart") != null) {
jvmArgs("-Dviaproxy.gui.autoStart")
}
doFirst {
val jarsDir = file("$workingDir/jars")
jarsDir.mkdirs()
file("$jarsDir/${project.name}.jar").writeBytes(tasks.shadowJar.get().archiveFile.get().asFile.readBytes())
}
doLast {
file("$workingDir/jars/${project.name}.jar").delete()
file("$workingDir/logs").deleteRecursively()
if (System.getProperty("viaproxy.disableExtraPlatforms") != null) {
jvmArgs("-Dviaproxy.enableViaBedrock=false", "-Dviaproxy.enableViaLegacy=false", "-Dviaproxy.enableViaAprilFools=false")
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2023 ViaVersion and contributors
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,7 +17,10 @@
*/
package com.viaversion.viabackwards;
import com.viaversion.viabackwards.api.DialogStyleConfig;
import com.viaversion.viaversion.util.ChatColorUtil;
import com.viaversion.viaversion.util.Config;
import com.viaversion.viaversion.util.ConfigSection;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
@@ -36,9 +39,15 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
private boolean handlePingsAsInvAcknowledgements;
private boolean bedrockAtY0;
private boolean sculkShriekersToCryingObsidian;
private boolean scaffoldingToWater;
private boolean mapDarknessEffect;
private boolean mapCustomModelData;
private boolean mapDisplayEntities;
private boolean suppressEmulationWarnings;
private boolean dialogsViaChests;
private DialogStyleConfig dialogStyleConfig;
private boolean codeOfConductAsDialog;
private boolean passOriginalItemNameToResourcePacks;
public ViaBackwardsConfig(File configFile, Logger logger) {
super(configFile, logger);
@@ -59,9 +68,37 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
handlePingsAsInvAcknowledgements = getBoolean("handle-pings-as-inv-acknowledgements", false);
bedrockAtY0 = getBoolean("bedrock-at-y-0", false);
sculkShriekersToCryingObsidian = getBoolean("sculk-shriekers-to-crying-obsidian", false);
scaffoldingToWater = getBoolean("scaffolding-to-water", false);
mapDarknessEffect = getBoolean("map-darkness-effect", true);
mapCustomModelData = getBoolean("map-custom-model-data", true);
mapDisplayEntities = getBoolean("map-display-entities", true);
suppressEmulationWarnings = getBoolean("suppress-emulation-warnings", false);
dialogsViaChests = getBoolean("dialogs-via-chests", true);
dialogStyleConfig = loadDialogStyleConfig(getSection("dialog-style"));
codeOfConductAsDialog = getBoolean("code-of-conduct-as-dialog", true);
passOriginalItemNameToResourcePacks = getBoolean("pass-original-item-name-to-resource-packs", true);
}
private DialogStyleConfig loadDialogStyleConfig(final ConfigSection section) {
return new DialogStyleConfig(
getString(section, "page-navigation-title", "&9&lPage navigation"),
getString(section, "page-navigation-next", "&9Left click: &6Go to next page"),
getString(section, "page-navigation-previous", "&9Right click: &6Go to previous page"),
getString(section, "increase-value", "&9Left click: &6Increase value by %s"),
getString(section, "decrease-value", "&9Right click: &6Decrease value by %s"),
getString(section, "value-range", "&7(Value between &a%s &7and &a%s&7)"),
getString(section, "next-option", "&9Left click: &6Go to next option"),
getString(section, "previous-option", "&9Right click: &6Go to previous option"),
getString(section, "current-value", "&7Current value: &a%s"),
getString(section, "edit-value", "&9Left click: &6Edit text"),
getString(section, "set-text", "&9Left click/close: &6Set text"),
getString(section, "close", "&9Left click: &6Close"),
getString(section, "toggle-value", "&9Left click: &6Toggle value")
);
}
protected String getString(final ConfigSection section, final String key, final String def) {
return ChatColorUtil.translateAlternateColorCodes(section.getString(key, def));
}
@Override
@@ -104,6 +141,11 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
return sculkShriekersToCryingObsidian;
}
@Override
public boolean scaffoldingToWater() {
return scaffoldingToWater;
}
@Override
public boolean mapDarknessEffect() {
return mapDarknessEffect;
@@ -114,11 +156,36 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
return mapCustomModelData;
}
@Override
public boolean mapDisplayEntities() {
return mapDisplayEntities;
}
@Override
public boolean suppressEmulationWarnings() {
return suppressEmulationWarnings;
}
@Override
public boolean dialogsViaChests() {
return dialogsViaChests;
}
@Override
public DialogStyleConfig dialogStyleConfig() {
return dialogStyleConfig;
}
@Override
public boolean codeOfConductAsDialog() {
return codeOfConductAsDialog;
}
@Override
public boolean passOriginalItemNameToResourcePacks() {
return passOriginalItemNameToResourcePacks;
}
@Override
public URL getDefaultConfigURL() {
return getClass().getClassLoader().getResource("assets/viabackwards/config.yml");
@@ -0,0 +1,53 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards;
import com.viaversion.viabackwards.api.ViaBackwardsPlatform;
import com.viaversion.viaversion.api.Via;
import java.io.File;
import java.util.logging.Logger;
public class ViaBackwardsPlatformImpl implements ViaBackwardsPlatform {
private final Logger logger;
public ViaBackwardsPlatformImpl() {
logger = Via.getPlatform().createLogger("ViaBackwards");
init(new File(getDataFolder(), "viabackwards.yml"));
enable();
}
@Override
public Logger getLogger() {
return logger;
}
@Override
public void disable() {
}
@Override
public File getDataFolder() {
return Via.getPlatform().getDataFolder();
}
@Override
public boolean isOutdated() {
return false;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,17 +18,20 @@
package com.viaversion.viabackwards.api;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.text.TranslatableRewriter;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.protocol.registration.BackwardsRegistrations;
import com.viaversion.viabackwards.utils.BackwardsProtocolLogger;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.util.ProtocolLogger;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class BackwardsProtocol<CU extends ClientboundPacketType, CM extends ClientboundPacketType, SM extends ServerboundPacketType, SU extends ServerboundPacketType>
extends AbstractProtocol<CU, CM, SM, SU> {
@Deprecated
protected BackwardsProtocol() {
}
@@ -37,36 +40,29 @@ public abstract class BackwardsProtocol<CU extends ClientboundPacketType, CM ext
super(oldClientboundPacketEnum, clientboundPacketEnum, oldServerboundPacketEnum, serverboundPacketEnum);
}
/**
* Waits for the given protocol to be loaded to then asynchronously execute the runnable for this protocol.
*/
protected void executeAsyncAfterLoaded(Class<? extends Protocol> protocolClass, Runnable runnable) {
Via.getManager().getProtocolManager().addMappingLoaderFuture(getClass(), protocolClass, runnable);
@Override
protected void applySharedRegistrations() {
super.applySharedRegistrations();
BackwardsRegistrations.registrations().applyMatching(this);
}
@Override
protected void registerPackets() {
super.registerPackets();
final BackwardsMappingData mappingData = getMappingData();
if (mappingData != null && mappingData.getViaVersionProtocolClass() != null) {
executeAsyncAfterLoaded(mappingData.getViaVersionProtocolClass(), this::loadMappingData);
}
protected ProtocolLogger createLogger() {
return new BackwardsProtocolLogger(getClass());
}
@Override
public boolean hasMappingDataToLoad() {
// Manually load them later, since they depend on VV's mappings
return false;
public @Nullable Class<? extends Protocol<?, ?, ?, ?>> dependsOn() {
return getMappingData() != null ? getMappingData().getViaVersionProtocolClass() : null;
}
@Override
public @Nullable BackwardsMappingData getMappingData() { // Change return type to BackwardsMappings
public @Nullable BackwardsMappingData getMappingData() {
return null;
}
@Override
public @Nullable TranslatableRewriter getComponentRewriter() {
public @Nullable BackwardsRegistryRewriter getRegistryDataRewriter() {
return null;
}
}
@@ -0,0 +1,25 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.api;
public record DialogStyleConfig(String pageNavigationTitle, String pageNavigationNext, String pageNavigationPrevious,
String increaseValue, String decreaseValue, String valueRange, String nextOption,
String previousOption, String currentValue, String editValue, String setText,
String close, String toggleValue) {
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -78,6 +78,13 @@ public interface ViaBackwardsConfig extends Config {
*/
boolean sculkShriekerToCryingObsidian();
/**
* Shows scaffolding as water for 1.13.2 clients on 1.14+ servers. This fixes collision issues.
*
* @return true if enabled
*/
boolean scaffoldingToWater();
/**
* Maps the darkness effect to blindness for 1.18.2 clients on 1.19+ servers.
*
@@ -92,10 +99,47 @@ public interface ViaBackwardsConfig extends Config {
*/
boolean mapCustomModelData();
/**
* If enabled, 1.19.3 clients will receive display entities as armor stands with custom entity data on 1.19.4+ servers.
*
* @return true if enabled
*/
boolean mapDisplayEntities();
/**
* Suppresses warnings of missing emulations for certain features that are not supported (e.g. world height in 1.17+).
*
* @return true if enabled
*/
boolean suppressEmulationWarnings();
/**
* If enabled, dialogs will be shown via chest inventories for 1.21.5 clients on 1.21.6+ servers.
*
* @return true if enabled
*/
boolean dialogsViaChests();
/**
* Returns the dialog style configuration.
*
* @return the dialog style configuration
*/
DialogStyleConfig dialogStyleConfig();
/**
* If true, the code of conduct will be displayed as a dialog for 1.21.7 clients on 1.21.9+ servers.
*
* @return true if enabled
*/
boolean codeOfConductAsDialog();
/**
* Injects the original vanilla 1.21.4+ item name into custom_model_data strings for resource packs.
* Disable if your server creates custom items using modern items as their base.
* Tip: For server custom items, base them on items in the game before 1.21.4 (e.g. saddle) to ensure compatibility.
*
* @return true if enabled
*/
boolean passOriginalItemNameToResourcePacks();
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,47 +21,56 @@ package com.viaversion.viabackwards.api;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.ViaBackwardsConfig;
import com.viaversion.viabackwards.api.data.TranslatableMappings;
import com.viaversion.viabackwards.protocol.v1_11to1_10.Protocol1_11To1_10;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.Protocol1_12To1_11_1;
import com.viaversion.viabackwards.protocol.registration.BackwardsRegistrations;
import com.viaversion.viabackwards.protocol.v1_10to1_9_3.Protocol1_10To1_9_3;
import com.viaversion.viabackwards.protocol.v1_11_1to1_11.Protocol1_11_1To1_11;
import com.viaversion.viabackwards.protocol.v1_12_2to1_12_1.Protocol1_12_2To1_12_1;
import com.viaversion.viabackwards.protocol.v1_13to1_12_2.Protocol1_13To1_12_2;
import com.viaversion.viabackwards.protocol.v1_11to1_10.Protocol1_11To1_10;
import com.viaversion.viabackwards.protocol.v1_12_1to1_12.Protocol1_12_1To1_12;
import com.viaversion.viabackwards.protocol.v1_13_2to1_13_1.Protocol1_13_2To1_13_1;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.Protocol1_14To1_13_2;
import com.viaversion.viabackwards.protocol.v1_12_2to1_12_1.Protocol1_12_2To1_12_1;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.Protocol1_12To1_11_1;
import com.viaversion.viabackwards.protocol.v1_13_1to1_13.Protocol1_13_1To1_13;
import com.viaversion.viabackwards.protocol.v1_13_2to1_13_1.Protocol1_13_2To1_13_1;
import com.viaversion.viabackwards.protocol.v1_13to1_12_2.Protocol1_13To1_12_2;
import com.viaversion.viabackwards.protocol.v1_14_1to1_14.Protocol1_14_1To1_14;
import com.viaversion.viabackwards.protocol.v1_14_2to1_14_1.Protocol1_14_2To1_14_1;
import com.viaversion.viabackwards.protocol.v1_14_3to1_14_2.Protocol1_14_3To1_14_2;
import com.viaversion.viabackwards.protocol.v1_14_4to1_14_3.Protocol1_14_4To1_14_3;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.Protocol1_15To1_14_4;
import com.viaversion.viabackwards.protocol.v1_14_1to1_14.Protocol1_14_1To1_14;
import com.viaversion.viabackwards.protocol.v1_15_2to1_15_1.Protocol1_15_2To1_15_1;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.Protocol1_16To1_15_2;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.Protocol1_14To1_13_2;
import com.viaversion.viabackwards.protocol.v1_15_1to1_15.Protocol1_15_1To1_15;
import com.viaversion.viabackwards.protocol.v1_15_2to1_15_1.Protocol1_15_2To1_15_1;
import com.viaversion.viabackwards.protocol.v1_15to1_14_4.Protocol1_15To1_14_4;
import com.viaversion.viabackwards.protocol.v1_16_1to1_16.Protocol1_16_1To1_16;
import com.viaversion.viabackwards.protocol.v1_16_2to1_16_1.Protocol1_16_2To1_16_1;
import com.viaversion.viabackwards.protocol.v1_16_3to1_16_2.Protocol1_16_3To1_16_2;
import com.viaversion.viabackwards.protocol.v1_16_4to1_16_3.Protocol1_16_4To1_16_3;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.Protocol1_17To1_16_4;
import com.viaversion.viabackwards.protocol.v1_16_1to1_16.Protocol1_16_1To1_16;
import com.viaversion.viabackwards.protocol.v1_18to1_17_1.Protocol1_18To1_17_1;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.Protocol1_16To1_15_2;
import com.viaversion.viabackwards.protocol.v1_17_1to1_17.Protocol1_17_1To1_17;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viabackwards.protocol.v1_17to1_16_4.Protocol1_17To1_16_4;
import com.viaversion.viabackwards.protocol.v1_18_2to1_18.Protocol1_18_2To1_18;
import com.viaversion.viabackwards.protocol.v1_18to1_17_1.Protocol1_18To1_17_1;
import com.viaversion.viabackwards.protocol.v1_19_1to1_19.Protocol1_19_1To1_19;
import com.viaversion.viabackwards.protocol.v1_19_3to1_19_1.Protocol1_19_3To1_19_1;
import com.viaversion.viabackwards.protocol.v1_19_4to1_19_3.Protocol1_19_4To1_19_3;
import com.viaversion.viabackwards.protocol.v1_21_4to1_21_2.Protocol1_21_4To1_21_2;
import com.viaversion.viabackwards.protocol.v1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viabackwards.protocol.v1_19_1to1_19.Protocol1_19_1To1_19;
import com.viaversion.viabackwards.protocol.v1_19to1_18_2.Protocol1_19To1_18_2;
import com.viaversion.viabackwards.protocol.v1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viabackwards.protocol.v1_20_3to1_20_2.Protocol1_20_3To1_20_2;
import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.Protocol1_20_5To1_20_3;
import com.viaversion.viabackwards.protocol.v1_20_2to1_20.Protocol1_20_2To1_20;
import com.viaversion.viabackwards.protocol.v1_20to1_19_4.Protocol1_20To1_19_4;
import com.viaversion.viabackwards.protocol.v1_21_11to1_21_9.Protocol1_21_11To1_21_9;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.Protocol1_21_2To1_21;
import com.viaversion.viabackwards.protocol.v1_21_2to1_21.task.PlayerPacketsTickTask;
import com.viaversion.viabackwards.protocol.v1_21_4to1_21_2.Protocol1_21_4To1_21_2;
import com.viaversion.viabackwards.protocol.v1_21_5to1_21_4.Protocol1_21_5To1_21_4;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.Protocol1_21_6To1_21_5;
import com.viaversion.viabackwards.protocol.v1_21_6to1_21_5.task.ChestDialogViewTask;
import com.viaversion.viabackwards.protocol.v1_21_7to1_21_6.Protocol1_21_7To1_21_6;
import com.viaversion.viabackwards.protocol.v1_21_9to1_21_7.Protocol1_21_9To1_21_7;
import com.viaversion.viabackwards.protocol.v1_21to1_20_5.Protocol1_21To1_20_5;
import com.viaversion.viabackwards.protocol.v1_9_3to1_9_1.Protocol1_9_3To1_9_1;
import com.viaversion.viabackwards.protocol.v1_10to1_9_3.Protocol1_10To1_9_3;
import com.viaversion.viabackwards.protocol.v1_9_1to1_9.Protocol1_9_1To1_9;
import com.viaversion.viabackwards.protocol.v1_9_3to1_9_1.Protocol1_9_3To1_9_1;
import com.viaversion.viabackwards.protocol.v26_1to1_21_11.Protocol26_1To1_21_11;
import com.viaversion.viabackwards.protocol.v26_2to26_1.Protocol26_2To26_1;
import com.viaversion.viabackwards.protocol.v26_3to26_2.Protocol26_3To26_2;
import com.viaversion.viabackwards.utils.VersionInfo;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
@@ -73,13 +82,16 @@ import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "5.3.2";
String MINIMUM_VV_VERSION = "5.12.2";
default void init(final File configFile) {
init(new ViaBackwardsConfig(configFile, getLogger()));
}
/**
* Initialize ViaBackwards.
*/
default void init(final File configFile) {
ViaBackwardsConfig config = new ViaBackwardsConfig(configFile, getLogger());
default void init(final com.viaversion.viabackwards.api.ViaBackwardsConfig config) {
config.reload();
Via.getManager().getConfigurationProvider().register(config);
@@ -96,6 +108,8 @@ public interface ViaBackwardsPlatform {
TranslatableMappings.loadTranslatables();
getLogger().info("Registering protocols...");
BackwardsRegistrations.apply();
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_9_1To1_9(), ProtocolVersion.v1_9, ProtocolVersion.v1_9_1);
protocolManager.registerProtocol(new Protocol1_9_3To1_9_1(), Arrays.asList(ProtocolVersion.v1_9_1, ProtocolVersion.v1_9_2), ProtocolVersion.v1_9_3);
@@ -148,6 +162,15 @@ public interface ViaBackwardsPlatform {
protocolManager.registerProtocol(new Protocol1_21_2To1_21(), ProtocolVersion.v1_21, ProtocolVersion.v1_21_2);
protocolManager.registerProtocol(new Protocol1_21_4To1_21_2(), ProtocolVersion.v1_21_2, ProtocolVersion.v1_21_4);
protocolManager.registerProtocol(new Protocol1_21_5To1_21_4(), ProtocolVersion.v1_21_4, ProtocolVersion.v1_21_5);
protocolManager.registerProtocol(new Protocol1_21_6To1_21_5(), ProtocolVersion.v1_21_5, ProtocolVersion.v1_21_6);
protocolManager.registerProtocol(new Protocol1_21_7To1_21_6(), ProtocolVersion.v1_21_6, ProtocolVersion.v1_21_7);
protocolManager.registerProtocol(new Protocol1_21_9To1_21_7(), ProtocolVersion.v1_21_7, ProtocolVersion.v1_21_9);
protocolManager.registerProtocol(new Protocol1_21_11To1_21_9(), ProtocolVersion.v1_21_9, ProtocolVersion.v1_21_11);
protocolManager.registerProtocol(new Protocol26_1To1_21_11(), ProtocolVersion.v1_21_11, ProtocolVersion.v26_1);
protocolManager.registerProtocol(new Protocol26_2To26_1(), ProtocolVersion.v26_1, ProtocolVersion.v26_2);
protocolManager.registerProtocol(new Protocol26_3To26_2(), ProtocolVersion.v26_2, ProtocolVersion.v26_3);
}
default void enable() {
@@ -155,6 +178,10 @@ public interface ViaBackwardsPlatform {
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_21_2)) {
Via.getPlatform().runRepeatingSync(new PlayerPacketsTickTask(), 1L);
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_21_6)) {
Via.getPlatform().runRepeatingSync(new ChestDialogViewTask(), 20L);
}
}
/**
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,6 +18,10 @@
package com.viaversion.viabackwards.api.data;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.Via;
@@ -30,12 +34,7 @@ import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectArrayMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.Key;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -45,8 +44,6 @@ public class BackwardsMappingData extends MappingDataBase {
private final Class<? extends Protocol<?, ?, ?, ?>> vvProtocolClass;
protected Int2ObjectMap<MappedItem> backwardsItemMappings;
private Map<String, String> backwardsSoundMappings;
private Map<String, String> entityNames;
private Int2ObjectMap<String> enchantmentNames;
public BackwardsMappingData(final String unmappedVersion, final String mappedVersion) {
@@ -61,43 +58,23 @@ public class BackwardsMappingData extends MappingDataBase {
@Override
protected void loadExtras(final CompoundTag data) {
final CompoundTag itemNames = data.getCompoundTag("itemnames");
if (itemNames != null) {
final CompoundTag itemCustomModelDatas = data.getCompoundTag("custom_model_data");
if (itemCustomModelDatas != null) {
Preconditions.checkNotNull(itemMappings);
backwardsItemMappings = new Int2ObjectOpenHashMap<>(itemNames.size());
final CompoundTag extraItemData = data.getCompoundTag("itemdata");
for (final Map.Entry<String, Tag> entry : itemNames.entrySet()) {
final StringTag name = (StringTag) entry.getValue();
final int id = Integer.parseInt(entry.getKey());
Integer customModelData = null;
if (extraItemData != null && extraItemData.contains(entry.getKey())) {
final CompoundTag entryTag = extraItemData.getCompoundTag(entry.getKey());
final NumberTag customModelDataTag = entryTag.getNumberTag("custom_model_data");
customModelData = customModelDataTag != null ? customModelDataTag.asInt() : null;
}
backwardsItemMappings.put(id, new MappedItem(getNewItemId(id), name.getValue(), customModelData));
}
backwardsItemMappings = new Int2ObjectOpenHashMap<>(itemCustomModelDatas.size());
loadBackwardsItemMappings(itemCustomModelDatas);
}
this.entityNames = loadNameByStringMappings(data, "entitynames");
this.enchantmentNames = loadNameByIdMappings(data, "enchantmentnames");
this.backwardsSoundMappings = loadNameByStringMappings(data, "soundnames");
}
private @Nullable Map<String, String> loadNameByStringMappings(final CompoundTag data, final String key) {
final CompoundTag nameMappings = data.getCompoundTag(key);
if (nameMappings == null) {
return null;
protected void loadBackwardsItemMappings(final CompoundTag itemCustomModelDatas) {
for (final Map.Entry<String, Tag> entry : itemCustomModelDatas.entrySet()) {
final int id = Integer.parseInt(entry.getKey());
final int customModelData = ((NumberTag) entry.getValue()).asInt();
final String identifier = getFullItemMappings().identifier(id);
final String fallbackName = unmappedVersion + " " + nameFromIdentifier(identifier);
backwardsItemMappings.put(id, new MappedItem(getNewItemId(id), identifier, fallbackName, customModelData));
}
final Map<String, String> map = new HashMap<>(nameMappings.size());
for (final Map.Entry<String, Tag> entry : nameMappings.entrySet()) {
final StringTag mappedTag = (StringTag) entry.getValue();
map.put(entry.getKey(), mappedTag.getValue());
}
return map;
}
private @Nullable Int2ObjectMap<String> loadNameByIdMappings(final CompoundTag data, final String key) {
@@ -161,18 +138,7 @@ public class BackwardsMappingData extends MappingDataBase {
}
public @Nullable String getMappedNamedSound(final String id) {
if (backwardsSoundMappings == null) {
return null;
}
return backwardsSoundMappings.get(Key.stripMinecraftNamespace(id));
}
public @Nullable String mappedEntityName(final String entityName) {
if (entityNames == null) {
getLogger().log(Level.SEVERE, "No entity mappings found when requesting them for " + entityName, new RuntimeException());
return null;
}
return entityNames.get(entityName);
return getFullSoundMappings().mappedIdentifier(id);
}
public @Nullable String mappedEnchantmentName(final int enchantmentId) {
@@ -187,10 +153,6 @@ public class BackwardsMappingData extends MappingDataBase {
return backwardsItemMappings;
}
public @Nullable Map<String, String> getBackwardsSoundMappings() {
return backwardsSoundMappings;
}
public @Nullable Class<? extends Protocol<?, ?, ?, ?>> getViaVersionProtocolClass() {
return vvProtocolClass;
}
@@ -204,4 +166,12 @@ public class BackwardsMappingData extends MappingDataBase {
protected @Nullable CompoundTag readMappingsFile(final String name) {
return BackwardsMappingDataLoader.INSTANCE.loadNBTFromDir(name);
}
public static String nameFromIdentifier(final String identifier) {
final StringBuilder result = new StringBuilder();
for (final String split : Key.stripMinecraftNamespace(identifier).split("_")) {
result.append(' ').append(Character.toUpperCase(split.charAt(0))).append(split.substring(1));
}
return result.substring(1);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,10 +17,10 @@
*/
package com.viaversion.viabackwards.api.data;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import java.io.File;
import java.io.IOException;
import java.util.Map;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,26 +17,43 @@
*/
package com.viaversion.viabackwards.api.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.ComponentUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.util.Key;
public class MappedItem {
private final int id;
private final String jsonName;
private final Tag tagName;
private final Integer customModelData;
private final int customModelData;
public MappedItem(final int id, final String name) {
this(id, name, null);
public MappedItem(final int id, String identifier, final String fallbackName, final int customModelData) {
this.id = id;
identifier = Key.stripMinecraftNamespace(identifier);
final String translateKey = "vb.item." + identifier;
this.jsonName = itemJsonName(fallbackName);
this.tagName = itemTagName(translateKey, fallbackName);
this.customModelData = customModelData;
}
public MappedItem(final int id, final String name, @Nullable final Integer customModelData) {
this.id = id;
this.jsonName = ComponentUtil.legacyToJsonString("§f" + name, true);
this.tagName = ComponentUtil.jsonStringToTag(jsonName);
this.customModelData = customModelData;
// Make explicitly non-italic and white to override default item formatting.
// Properly parsing is expensive...
private static String itemJsonName(final String name) {
return """
{"italic":false,"color":"white","text":%s}
""".formatted(new JsonPrimitive(name).toString());
}
private static Tag itemTagName(final String translateKey, final String fallbackName) {
// Proper translate with fallback field (valid for 1.19.4+ clients)
final CompoundTag tag = new CompoundTag();
tag.putString("color", "white");
tag.putString("translate", translateKey);
tag.putString("fallback", fallbackName);
tag.putBoolean("italic", false);
return tag;
}
public int id() {
@@ -48,10 +65,10 @@ public class MappedItem {
}
public Tag tagName() {
return tagName;
return tagName.copy();
}
public @Nullable Integer customModelData() {
public int customModelData() {
return customModelData;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -0,0 +1,48 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.api.entities;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
/**
* Storage object used within {@link TrackedEntity} to track the scaling state of an entity.
* This ensures that scale updates are only sent when the calculated scale actually changes.
*/
public final class EntityScaleData implements StorableObject {
private boolean isBaby;
private float scale = 1.0f;
public boolean isBaby() {
return isBaby;
}
public void setBaby(boolean baby) {
this.isBaby = baby;
}
public float scale() {
return scale;
}
public void setScale(float scale) {
this.scale = scale;
}
}
@@ -0,0 +1,102 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.api.entities;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEvent;
/**
* A helper for injecting entity scaling on older clients.
* This helper listens for the baby entity data flag and sends an UPDATE_ATTRIBUTES packet
* to scale the entity, since older clients might not support the newer entity variants natively.
*/
public class EntityScaleHelper {
private final ClientboundPacketType updateAttributesPacket;
private final EntityRewriter<?, ?> rewriter;
/**
* Constructs a new entity scale helper.
*
* @param rewriter entity rewriter
* @param updateAttributesPacket UPDATE_ATTRIBUTES packet of the mapped protocol
* @param <CM> mapped clientbound packet type
*/
public <CM extends ClientboundPacketType, P extends Protocol<?, CM, ?, ?>> EntityScaleHelper(final EntityRewriter<?, P> rewriter, final CM updateAttributesPacket) {
this.rewriter = rewriter;
this.updateAttributesPacket = updateAttributesPacket;
}
/**
* Registers a scaling factor for a specific baby entity type.
*
* @param type entity type that requires scaling when it is a baby
* @param babyScaleFactor multiplier to apply to the minecraft:scale attribute when it is a baby
* @param babyIndex entity data index for the baby property in this specific protocol
*/
public void addBabyScale(final EntityType type, final float babyScaleFactor, final int babyIndex) {
rewriter.filter().type(type).index(babyIndex).handler(((event, data) -> trackAndSend(event, data, babyScaleFactor)));
}
/**
* Checks the entity data, tracks the scale state and sends an UPDATE_ATTRIBUTES packet if needed.
*/
public void trackAndSend(final EntityDataHandlerEvent event, final EntityData data, final float babyScaleFactor) {
if (event.trackedEntity() == null) {
return;
}
EntityScaleData scaleData = event.trackedEntity().get(EntityScaleData.class);
if (scaleData == null) {
scaleData = new EntityScaleData();
event.trackedEntity().put(scaleData);
}
final boolean isBaby = data.value();
if (scaleData.isBaby() == isBaby) {
return;
}
scaleData.setBaby(isBaby);
scaleData.setScale(isBaby ? babyScaleFactor : 1.0f);
final FullMappings attributeMappings = rewriter.protocol().getMappingData().getAttributeMappings();
int attributeId = attributeMappings.mappedId("scale");
if (attributeId == -1) {
attributeId = attributeMappings.mappedId("generic.scale");
Preconditions.checkArgument(attributeId != -1);
}
final PacketWrapper attributesPacket = PacketWrapper.create(updateAttributesPacket, event.user());
attributesPacket.write(Types.VAR_INT, event.entityId());
attributesPacket.write(Types.VAR_INT, 1); // 1 attribute
attributesPacket.write(Types.VAR_INT, attributeId);
attributesPacket.write(Types.DOUBLE, (double) scaleData.scale());
attributesPacket.write(Types.VAR_INT, 0); // 0 modifiers
attributesPacket.send(rewriter.protocol().getClass());
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,12 +18,10 @@
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viabackwards.api.rewriters.EntityRewriterBase;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.ProtocolLogger;
import java.util.function.Supplier;
public class EntityPositionHandler {
@@ -32,7 +30,6 @@ public class EntityPositionHandler {
private final EntityRewriterBase<?, ?> entityRewriter;
private final Class<? extends EntityPositionStorage> storageClass;
private final Supplier<? extends EntityPositionStorage> storageSupplier;
private boolean warnedForMissingEntity;
public EntityPositionHandler(EntityRewriterBase<?, ?> entityRewriter,
Class<? extends EntityPositionStorage> storageClass, Supplier<? extends EntityPositionStorage> storageSupplier) {
@@ -47,28 +44,22 @@ public class EntityPositionHandler {
}
public void cacheEntityPosition(PacketWrapper wrapper, double x, double y, double z, boolean create, boolean relative) {
int entityId = wrapper.get(Types.VAR_INT, 0);
StoredEntityData storedEntity = entityRewriter.tracker(wrapper.user()).entityData(entityId);
if (storedEntity == null) {
if (Via.getManager().isDebug()) { // There is too many plugins violating this out there, and reading seems to be hard! :>
ProtocolLogger logger = entityRewriter.protocol().getLogger();
logger.warning("Stored entity with id " + entityId + " missing at position: " + x + " - " + y + " - " + z + " in " + storageClass.getSimpleName());
if (entityId == -1 && x == 0 && y == 0 && z == 0) {
logger.warning("DO NOT REPORT THIS TO VIA, THIS IS A PLUGIN ISSUE");
} else if (!warnedForMissingEntity) {
warnedForMissingEntity = true;
logger.warning("This is very likely caused by a plugin sending a teleport packet for an entity outside of the player's range.");
}
}
cacheEntityPosition(wrapper, wrapper.get(Types.VAR_INT, 0), x, y, z, create, relative);
}
public void cacheEntityPosition(PacketWrapper wrapper, int entityId, double x, double y, double z, boolean create, boolean relative) {
final TrackedEntity entity = entityRewriter.tracker(wrapper.user()).entity(entityId);
if (entity == null) {
// Bad plugins
return;
}
EntityPositionStorage positionStorage;
if (create) {
positionStorage = storageSupplier.get();
storedEntity.put(positionStorage);
entity.put(positionStorage);
} else {
positionStorage = storedEntity.get(storageClass);
positionStorage = entity.get(storageClass);
if (positionStorage == null) {
entityRewriter.protocol().getLogger().warning("Stored entity with id " + entityId + " missing " + storageClass.getSimpleName());
return;
@@ -83,9 +74,9 @@ public class EntityPositionHandler {
}
public EntityPositionStorage getStorage(UserConnection user, int entityId) {
StoredEntityData storedEntity = entityRewriter.tracker(user).entityData(entityId);
final TrackedEntity entity = entityRewriter.tracker(user).entity(entityId);
EntityPositionStorage entityStorage;
if (storedEntity == null || (entityStorage = storedEntity.get(EntityPositionStorage.class)) == null) {
if (entity == null || (entityStorage = entity.get(EntityPositionStorage.class)) == null) {
entityRewriter.protocol().getLogger().warning("Untracked entity with id " + entityId + " in " + storageClass.getSimpleName());
return null;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,7 +17,9 @@
*/
package com.viaversion.viabackwards.api.entities.storage;
public abstract class EntityPositionStorage {
import com.viaversion.viaversion.api.connection.StorableObject;
public abstract class EntityPositionStorage implements StorableObject {
private double x;
private double y;
private double z;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,9 +18,11 @@
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.util.ComponentUtil;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -30,18 +32,22 @@ public class EntityReplacement {
private final int id;
private final int replacementId;
private final String key;
private final String translateKey;
private final String fallbackName;
private ComponentType componentType = ComponentType.NONE;
private EntityDataCreator defaultData;
public EntityReplacement(BackwardsProtocol<?, ?, ?, ?> protocol, EntityType type, int replacementId) {
this(protocol, type.name(), type.getId(), replacementId);
this(protocol, type.name().toLowerCase(Locale.ROOT), type.getId(), replacementId);
}
public EntityReplacement(BackwardsProtocol<?, ?, ?, ?> protocol, String key, int id, int replacementId) {
this.protocol = protocol;
this.id = id;
this.replacementId = replacementId;
this.key = key.toLowerCase(Locale.ROOT);
this.key = key;
this.translateKey = "vb.entity." + key;
this.fallbackName = BackwardsMappingData.nameFromIdentifier(this.key);
}
public EntityReplacement jsonName() {
@@ -73,24 +79,26 @@ public class EntityReplacement {
}
/**
* @return custom mobname, can be either a String or a JsonElement
* Returns the custom entity name. Can be either a {@link String}, {@link StringTag} or {@link com.viaversion.viaversion.libs.gson.JsonElement}.
*
* @return custom entity name
*/
public @Nullable Object entityName() {
if (componentType == ComponentType.NONE) {
return null;
}
final String name = protocol.getMappingData().mappedEntityName(key);
if (name == null) {
return null;
}
if (componentType == ComponentType.JSON) {
return ComponentUtil.legacyToJson(name);
return ComponentUtil.plainToJson(fallbackName); // Pass on as plain, with or without section symbols
} else if (componentType == ComponentType.TAG) {
return new StringTag(name);
final CompoundTag tag = new CompoundTag();
tag.putString("color", "white");
tag.putString("translate", translateKey);
tag.putString("fallback", fallbackName);
tag.putBoolean("italic", false);
return tag;
}
return name;
return fallbackName;
}
public int replacementId() {
@@ -0,0 +1,57 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
public class PlayerPosRotStorage extends PlayerPositionStorage {
private float yRot; // yaw
private float xRot; // pitch
public float yRot() {
return yRot;
}
public void setYRot(final float yRot) {
this.yRot = yRot;
}
public float xRot() {
return xRot;
}
public void setXRot(final float xRot) {
this.xRot = xRot;
}
public void setRotation(final float yRot, final float xRot) {
this.yRot = yRot;
this.xRot = xRot;
}
public void setRotFromPacket(final PacketWrapper wrapper) {
this.yRot = wrapper.passthrough(Types.FLOAT);
this.xRot = wrapper.passthrough(Types.FLOAT);
}
public void setPosRotFromPacket(final PacketWrapper wrapper) {
this.setPosFromPacket(wrapper);
this.setRotFromPacket(wrapper);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,15 +18,14 @@
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
public abstract class PlayerPositionStorage implements StorableObject {
public class PlayerPositionStorage implements StorableObject {
private double x;
private double y;
private double z;
protected PlayerPositionStorage() {
}
public double x() {
return x;
}
@@ -57,6 +56,12 @@ public abstract class PlayerPositionStorage implements StorableObject {
this.z = z;
}
public void setPosFromPacket(PacketWrapper wrapper) {
this.x = wrapper.passthrough(Types.DOUBLE);
this.y = wrapper.passthrough(Types.DOUBLE);
this.z = wrapper.passthrough(Types.DOUBLE);
}
public void addRelativePosition(double relX, double relY, double relZ) {
this.x += relX;
this.y += relY;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -0,0 +1,81 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
// 1.20.5-1.21.4
public class BackwardsFullStructuredItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends BackwardsProtocol<C, ?, ?, S>> extends BackwardsStructuredItemRewriter<C, S, T> {
public BackwardsFullStructuredItemRewriter(final T protocol) {
super(protocol);
}
@Override
public Item handleItemToServer(final UserConnection connection, final Item item) {
if (Item.isEmpty(item)) {
return item;
}
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
if (protocolInfo.serverProtocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_5)
&& !protocol.getEntityRewriter().tracker(connection).canInstaBuild()) {
// We don't actually need anything but the amount, id, and hashes.
// Just pass it on without deeper handling, only leaving custom data.
final CompoundTag customData = item.dataContainer().get(StructuredDataKey.CUSTOM_DATA);
if (customData == null) {
// Not valid
item.dataContainer().data().clear();
} else {
customData.keySet().removeIf(key -> !key.equals(ORIGINAL_HASHES_KEY));
item.dataContainer().data().keySet().removeIf(key -> key != StructuredDataKey.CUSTOM_DATA);
}
}
return super.handleItemToServer(connection, item);
}
@Override
protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) {
// Keep original hashes intact until 1.21.5
final Tag hashes = customData.get(ORIGINAL_HASHES_KEY);
super.restoreBackupData(item, container, customData);
if (hashes != null) {
customData.put(ORIGINAL_HASHES_KEY, hashes);
// Add back
if (!container.has(StructuredDataKey.CUSTOM_DATA)) {
container.set(StructuredDataKey.CUSTOM_DATA, customData);
customData.putBoolean(MARKER_KEY, true);
}
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,15 +24,20 @@ import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.MappedItem;
import com.viaversion.viabackwards.item.DataItemWithExtras;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
// <1.20.5
public class BackwardsItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends BackwardsProtocol<C, ?, ?, S>> extends BackwardsItemRewriterBase<C, S, T> {
@@ -52,29 +57,45 @@ public class BackwardsItemRewriter<C extends ClientboundPacketType, S extends Se
CompoundTag display = item.tag() != null ? item.tag().getCompoundTag("display") : null;
if (protocol.getComponentRewriter() != null && display != null) {
// Handle name and lore components
StringTag name = display.getStringTag("Name");
if (name != null) {
String newValue = protocol.getComponentRewriter().processText(connection, name.getValue()).toString();
if (!newValue.equals(name.getValue())) {
saveStringTag(display, name, "Name");
}
name.setValue(newValue);
final DataItemWithExtras fullItem;
if (item instanceof DataItemWithExtras) {
fullItem = (DataItemWithExtras) item;
} else {
item = fullItem = new DataItemWithExtras(item);
}
ListTag<StringTag> lore = display.getListTag("Lore", StringTag.class);
// Handle name and lore components
final JsonElement name = fullItem.name();
if (name != null) {
final JsonElement updatedName = name.deepCopy();
protocol.getComponentRewriter().processText(connection, updatedName);
if (!updatedName.equals(name)) {
final StringTag rawName = fullItem.rawName();
saveStringTag(display, rawName, "Name");
rawName.setValue(updatedName.toString());
}
}
final List<JsonElement> lore = fullItem.lore();
if (lore != null) {
boolean changed = false;
for (StringTag loreEntry : lore) {
String newValue = protocol.getComponentRewriter().processText(connection, loreEntry.getValue()).toString();
if (!changed && !newValue.equals(loreEntry.getValue())) {
// Backup original lore before doing any modifications
changed = true;
saveListTag(display, lore, "Lore");
final ListTag<StringTag> rawLore = fullItem.rawLore();
for (int i = 0; i < lore.size(); i++) {
final JsonElement loreEntry = lore.get(i);
final JsonElement updatedLoreEntry = loreEntry.deepCopy();
protocol.getComponentRewriter().processText(connection, updatedLoreEntry);
if (updatedLoreEntry.equals(loreEntry)) {
continue;
}
loreEntry.setValue(newValue);
if (!changed) {
// Backup original lore before doing any modifications
changed = true;
saveListTag(display, rawLore, "Lore");
}
final StringTag rawLoreEntry = rawLore.get(i);
rawLoreEntry.setValue(updatedLoreEntry.toString());
}
}
}
@@ -94,7 +115,7 @@ public class BackwardsItemRewriter<C extends ClientboundPacketType, S extends Se
item.setIdentifier(data.id());
// Add custom model data
if (data.customModelData() != null && !item.tag().contains("CustomModelData")) {
if (ViaBackwards.getConfig().passOriginalItemNameToResourcePacks() && !item.tag().contains("CustomModelData")) {
item.tag().putInt("CustomModelData", data.customModelData());
}
@@ -113,7 +134,7 @@ public class BackwardsItemRewriter<C extends ClientboundPacketType, S extends Se
public @Nullable Item handleItemToServer(UserConnection connection, @Nullable Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
item = super.handleItemToServer(connection, item);
if (item.tag() != null) {
Tag originalId = item.tag().remove(nbtTagName("id"));
if (originalId instanceof IntTag) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,19 +17,17 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.rewriter.ItemRewriter;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class BackwardsItemRewriterBase<C extends ClientboundPacketType, S extends ServerboundPacketType,
@@ -49,7 +47,7 @@ public abstract class BackwardsItemRewriterBase<C extends ClientboundPacketType,
@Override
public @Nullable Item handleItemToServer(UserConnection connection, @Nullable Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
item = super.handleItemToServer(connection, item);
restoreDisplayTag(item);
return item;
@@ -0,0 +1,139 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.TagUtil;
import java.util.Map;
public class BackwardsRegistryRewriter extends RegistryDataRewriter {
private final BackwardsProtocol<?, ?, ?, ?> protocol;
public BackwardsRegistryRewriter(final BackwardsProtocol<?, ?, ?, ?> protocol) {
super(protocol);
this.protocol = protocol;
}
@Override
public RegistryEntry[] handle(final UserConnection connection, final String key, final RegistryEntry[] entries) {
if (Key.stripMinecraftNamespace(key).equals("worldgen/biome")) {
for (final RegistryEntry entry : entries) {
final CompoundTag biome = (CompoundTag) entry.tag();
if (biome == null) {
continue;
}
final CompoundTag effects = biome.getCompoundTag("effects");
updateBiomeEffects(effects);
final CompoundTag attributes = biome.getCompoundTag("attributes");
if (attributes != null) {
updateAttributes(attributes);
}
}
}
return super.handle(connection, key, entries);
}
@Override
public void updateJukeboxSongs(final UserConnection connection, final RegistryEntry[] entries) {
super.updateJukeboxSongs(connection, entries);
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
updateSound((CompoundTag) entry.tag(), "sound_event");
}
}
@Override
protected boolean updateBlockState(final Tag blockStateTag) {
if (!(blockStateTag instanceof CompoundTag blockState) || blockState.getStringTag("Name") == null) {
return super.updateBlockState(blockStateTag);
}
// Up to 26.2, block states use "Name" and "Properties" instead of "id" and "properties"
final FullMappings blockMappings = protocol.getMappingData().getFullBlockMappings();
if (blockMappings == null) {
return false;
}
final int blockId = blockMappings.id(blockState.getString("Name"));
if (blockId == -1 || protocol.getMappingData().hasBlockChanged(blockId)) {
// Replace unknown or changed blocks with a dummy state, else the client will fail to load the registry
blockState.putString("Name", "minecraft:dirt");
blockState.remove("Properties");
return true;
}
return false;
}
private void updateBiomeEffects(final CompoundTag effects) {
updateSound(effects.getCompoundTag("mood_sound"), "sound");
updateSound(effects.getCompoundTag("additions_sound"), "sound");
updateSound(effects.getCompoundTag("music"), "sound");
updateSound(effects, "ambient_sound");
}
private void updateAttributes(final CompoundTag attributes) {
final CompoundTag backgroundMusic = TagUtil.getNamespacedCompoundTag(attributes, "audio/background_music");
if (backgroundMusic != null) {
updateSound(backgroundMusic.getCompoundTag("default"), "sound");
}
final CompoundTag ambientSounds = TagUtil.getNamespacedCompoundTag(attributes, "audio/ambient_sounds");
if (ambientSounds != null) {
updateSound(ambientSounds, "loop");
updateSound(ambientSounds, "mood");
updateSound(ambientSounds, "additions");
}
}
private void updateSound(final CompoundTag tag, final String name) {
if (tag == null) {
return;
}
final String sound = tag.getString(name);
if (sound == null) {
return;
}
final String mappedSound = protocol.getMappingData().getMappedNamedSound(sound);
if (mappedSound != null) {
tag.putString(name, mappedSound);
} else if (name.equals("sound_id")) {
// If it's already an inlined sound
tag.putString(name, "minecraft:intentionally_empty");
} else {
// Write as custom sound, so the id doesn't actually need to exist later on
final CompoundTag soundEvent = new CompoundTag();
soundEvent.putString("sound_id", "minecraft:intentionally_empty");
tag.put(name, soundEvent);
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.data.MappedItem;
@@ -31,6 +32,7 @@ import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
@@ -38,72 +40,46 @@ import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import com.viaversion.viaversion.util.ArrayUtil;
import com.viaversion.viaversion.util.Key;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
// 1.21.5+
public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends BackwardsProtocol<C, ?, ?, S>> extends StructuredItemRewriter<C, S, T> {
private static final int[] EMPTY_INT_ARRAY = new int[0];
private static final String GLOBAL_MODEL_DATA_MARKER = "VB|injected_cmd";
public BackwardsStructuredItemRewriter(
T protocol,
Type<Item> itemType, Type<Item[]> itemArrayType, Type<Item> mappedItemType, Type<Item[]> mappedItemArrayType,
Type<Item> itemCostType, Type<Item> optionalItemCostType, Type<Item> mappedItemCostType, Type<Item> mappedOptionalItemCostType
) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType, itemCostType, optionalItemCostType, mappedItemCostType, mappedOptionalItemCostType);
}
private final String nbtTagName;
public BackwardsStructuredItemRewriter(final T protocol, final Type<Item> itemType, final Type<Item[]> itemArrayType, final Type<Item> mappedItemType, final Type<Item[]> mappedItemArrayType) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType);
}
public BackwardsStructuredItemRewriter(final T protocol, final Type<Item> itemType, final Type<Item[]> itemArrayType) {
super(protocol, itemType, itemArrayType);
public BackwardsStructuredItemRewriter(T protocol) {
super(protocol);
this.nbtTagName = "VB|" + protocol.getClass().getSimpleName();
}
@Override
public Item handleItemToClient(final UserConnection connection, final Item item) {
if (item.isEmpty()) {
return item;
}
final StructuredDataContainer dataContainer = item.dataContainer();
updateItemDataComponentTypeIds(dataContainer, true);
protected void backupInconvertibleData(final UserConnection connection, final Item item, final StructuredDataContainer dataContainer, final CompoundTag backupTag) {
super.backupInconvertibleData(connection, item, dataContainer, backupTag);
final BackwardsMappingData mappingData = protocol.getMappingData();
final MappedItem mappedItem = mappingData != null ? mappingData.getMappedItem(item.identifier()) : null;
if (mappedItem == null) {
// Just rewrite the id
if (mappingData != null && mappingData.getItemMappings() != null) {
item.setIdentifier(mappingData.getNewItemId(item.identifier()));
}
updateItemDataComponents(connection, item, true);
return item;
return;
}
// Save original id, set remapped id
final CompoundTag tag = createCustomTag(item);
tag.putInt(nbtTagName("id"), item.identifier());
item.setIdentifier(mappedItem.id());
final CompoundTag customTag = createCustomTag(item);
customTag.putInt(nbtTagName("id"), item.identifier()); // Save original id
// Add custom model data
if (mappedItem.customModelData() != null) {
if (ViaBackwards.getConfig().passOriginalItemNameToResourcePacks()) {
if (connection.getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4)) {
if (!dataContainer.has(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4)) {
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4(
new float[]{mappedItem.customModelData().floatValue()},
new boolean[0],
new String[0],
EMPTY_INT_ARRAY
));
}
addCustomModelData(item, mappedItem, customTag);
} else if (!dataContainer.has(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5)) {
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, mappedItem.customModelData());
}
@@ -112,38 +88,61 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
// Set custom name - only done if there is no original one
if (!dataContainer.has(StructuredDataKey.CUSTOM_NAME)) {
dataContainer.set(StructuredDataKey.CUSTOM_NAME, mappedItem.tagName());
tag.putBoolean(nbtTagName("added_custom_name"), true);
customTag.putBoolean(nbtTagName("added_custom_name"), true);
}
}
updateItemDataComponents(connection, item, true);
return item;
private void addCustomModelData(final Item item, final MappedItem mappedItem, final CompoundTag customTag) {
final StructuredDataContainer dataContainer = item.dataContainer();
CustomModelData1_21_4 customModelData = dataContainer.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4);
if (customModelData == null) {
// Add both the identifier string and custom model data
customModelData = new CustomModelData1_21_4(
new float[]{mappedItem.customModelData()},
new boolean[0],
new String[]{protocol.getMappingData().getFullItemMappings().identifier(item.identifier())},
EMPTY_INT_ARRAY
);
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, customModelData);
// Add one global marker and one for this specific version, so it is removed at the correct protocol
customTag.putBoolean(GLOBAL_MODEL_DATA_MARKER, true);
customTag.putBoolean(nbtTagName("added_custom_model_data"), true);
} else if (!customTag.contains(GLOBAL_MODEL_DATA_MARKER)) {
final String identifier = protocol.getMappingData().getFullItemMappings().identifier(item.identifier());
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4(
customModelData.floats(), customModelData.booleans(), ArrayUtil.add(customModelData.strings(), identifier), customModelData.colors()
));
customTag.putBoolean(GLOBAL_MODEL_DATA_MARKER, true);
customTag.putString(nbtTagName("injected_custom_model_data"), identifier);
}
}
@Override
public Item handleItemToServer(final UserConnection connection, final Item item) {
if (item.isEmpty()) {
return item;
protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) {
super.restoreBackupData(item, container, customData);
if (removeBackupTag(customData, "id") instanceof final IntTag originalTag) {
item.setIdentifier(originalTag.asInt());
removeCustomTag(container, customData);
}
final StructuredDataContainer dataContainer = item.dataContainer();
updateItemDataComponentTypeIds(dataContainer, false);
final BackwardsMappingData mappingData = protocol.getMappingData();
if (mappingData != null && mappingData.getItemMappings() != null) {
item.setIdentifier(mappingData.getOldItemId(item.identifier()));
if (removeBackupTag(customData, "injected_custom_model_data") instanceof StringTag injectedCustomModelData) {
customData.remove(GLOBAL_MODEL_DATA_MARKER);
container.replace(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, customModelData -> {
final String target = injectedCustomModelData.getValue();
final String[] strings = customModelData.strings();
for (int i = 0; i < strings.length; i++) {
if (strings[i].equals(target)) {
// Remove the injected string
final String[] filteredStrings = ArrayUtil.remove(strings, i);
return new CustomModelData1_21_4(customModelData.floats(), customModelData.booleans(), filteredStrings, customModelData.colors());
}
}
return customModelData;
});
} else if (removeBackupTag(customData, "added_custom_model_data") != null) {
customData.remove(GLOBAL_MODEL_DATA_MARKER);
container.remove(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4);
}
final CompoundTag customData = dataContainer.get(StructuredDataKey.CUSTOM_DATA);
if (customData != null) {
if (customData.remove(nbtTagName("id")) instanceof final IntTag originalTag) {
item.setIdentifier(originalTag.asInt());
removeCustomTag(dataContainer, customData);
}
}
restoreTextComponents(item);
updateItemDataComponents(connection, item, false);
return item;
}
protected void saveListTag(CompoundTag tag, ListTag<?> original, String name) {
@@ -291,6 +290,20 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
}
}
protected void saveKeyData(final StructuredDataKey<Key> key, final StructuredDataContainer data, final CompoundTag backupTag) {
final Key value = data.get(key);
if (value != null) {
backupTag.putString(key.identifier(), value.original());
}
}
protected void restoreKeyData(final StructuredDataKey<Key> key, final StructuredDataContainer data, final CompoundTag backupTag) {
final String value = backupTag.getString(key.identifier());
if (value != null) {
data.set(key, Key.of(value));
}
}
protected void saveIntData(final StructuredDataKey<Integer> key, final StructuredDataContainer data, final CompoundTag backupTag) {
final Integer variant = data.get(key);
if (variant != null) {
@@ -319,8 +332,31 @@ public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S
}
}
protected void saveSoundEventHolder(final CompoundTag tag, final Holder<SoundEvent> holder) {
tag.put("sound_event", holderToTag(holder, this::saveSoundEvent));
}
protected void saveSoundEvent(final SoundEvent soundEvent, final CompoundTag tag) {
tag.putString("identifier", soundEvent.identifier());
if (soundEvent.fixedRange() != null) {
tag.putFloat("fixed_range", soundEvent.fixedRange());
}
}
protected Holder<SoundEvent> restoreSoundEventHolder(final CompoundTag tag) {
return restoreSoundEventHolder(tag, "sound_event");
}
protected Holder<SoundEvent> restoreSoundEventHolder(final CompoundTag tag, final String key) {
return restoreHolder(tag, key, soundEventTag -> {
final String identifier = soundEventTag.getString("identifier");
final FloatTag fixedRange = soundEventTag.getFloatTag("fixed_range");
return new SoundEvent(identifier, fixedRange != null ? fixedRange.asFloat() : null);
});
}
@Override
public String nbtTagName() {
return "VB|" + protocol.getClass().getSimpleName();
return this.nbtTagName;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,12 +17,12 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.utils.ChatUtil;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.util.Key;
import java.util.ArrayList;
import java.util.HashMap;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,8 +18,7 @@
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -37,110 +36,28 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
super(protocol, displayType, 2, displayVisibilityType, 3);
}
@Override
public void registerTrackerWithData(C packetType, EntityType fallingBlockType) {
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.passthrough(Types.UUID); // Entity UUID
wrapper.passthrough(Types.VAR_INT); // Entity Type
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
wrapper.passthrough(Types.INT); // Data
getSpawnTrackerWithDataHandler(fallingBlockType).handle(wrapper);
});
}
@Override
public void registerTrackerWithData1_19(C packetType, EntityType fallingBlockType) {
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity id
wrapper.passthrough(Types.UUID); // Entity UUID
wrapper.passthrough(Types.VAR_INT); // Entity type
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
wrapper.passthrough(Types.BYTE); // Head yaw
wrapper.passthrough(Types.VAR_INT); // Data
getSpawnTrackerWithDataHandler1_19(fallingBlockType).handle(wrapper);
});
}
public PacketHandler getSpawnTrackerWithDataHandler(EntityType fallingBlockType) {
public PacketHandler getSpawnTrackerWithDataHandler() {
return wrapper -> {
// Check against the UNMAPPED entity type
EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) {
int entityId = wrapper.get(Types.VAR_INT, 0);
int typeId = wrapper.get(Types.VAR_INT, 1);
TrackedEntity entity = trackAndRewrite(wrapper, typeId, entityId);
if (entity.entityType() == fallingBlockType()) {
int blockState = wrapper.get(Types.INT, 0);
wrapper.set(Types.INT, 0, protocol.getMappingData().getNewBlockStateId(blockState));
}
};
}
public PacketHandler getSpawnTrackerWithDataHandler1_19(EntityType fallingBlockType) {
return wrapper -> {
if (protocol.getMappingData() == null) {
return;
}
public void trackSpawnWithData1_19(final PacketWrapper wrapper, final int data) {
if (protocol.getMappingData() == null) {
return;
}
// Check against the UNMAPPED entity type
EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) {
int blockState = wrapper.get(Types.VAR_INT, 2);
wrapper.set(Types.VAR_INT, 2, protocol.getMappingData().getNewBlockStateId(blockState));
}
};
}
public void registerSpawnTracker(C packetType) {
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.passthrough(Types.UUID); // Entity UUID
wrapper.passthrough(Types.VAR_INT); // Entity Type
trackAndMapEntity(wrapper);
});
}
/**
* Returns a handler to track the current world and uncache entity data on world changes.
*
* @return handler to track the current world
*/
public PacketHandler worldTrackerHandlerByKey() {
return wrapper -> {
EntityTracker tracker = tracker(wrapper.user());
String world = wrapper.get(Types.STRING, 1);
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
tracker.clearEntities();
}
tracker.setCurrentWorld(world);
};
}
/**
* Sets the mapped entity id and returns the unmapped entity type.
*
* @param wrapper packet wrapper
* @return unmapped (!) entity type
*/
protected EntityType trackAndMapEntity(PacketWrapper wrapper) {
int entityId = wrapper.get(Types.VAR_INT, 0);
int typeId = wrapper.get(Types.VAR_INT, 1);
EntityType entityType = typeFromId(typeId);
if (entityType == null) {
return null;
TrackedEntity entity = trackAndRewrite(wrapper, typeId, entityId);
if (entity.entityType() == fallingBlockType()) {
wrapper.set(Types.VAR_INT, 2, protocol.getMappingData().getNewBlockStateId(data));
}
tracker(wrapper.user()).addEntity(wrapper.get(Types.VAR_INT, 0), entityType);
int mappedTypeId = newEntityId(entityType.getId());
if (typeId != mappedTypeId) {
wrapper.set(Types.VAR_INT, 1, mappedTypeId);
}
return entityType;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,8 +23,6 @@ import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.WrappedEntityData;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Particle;
@@ -39,7 +37,6 @@ import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEvent;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -86,12 +83,12 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
// Add it as new entity data
entityDataList.add(new EntityData(displayNameIndex, displayNameDataType, displayNameObject));
addDisplayVisibilityData(entityDataList);
} else if (displayName.getValue() == null || displayName.getValue().toString().isEmpty()) {
} else if (isEmptyDisplayName(displayName.getValue())) {
// Overwrite the existing null/empty display name
displayName.setValue(displayNameObject);
addDisplayVisibilityData(entityDataList);
}
} else if (displayName != null && (displayName.getValue() == null || displayName.getValue().toString().isEmpty())) {
} else if (displayName != null && (isEmptyDisplayName(displayName))) {
// Overwrite null/empty display name
displayName.setValue(displayNameObject);
addDisplayVisibilityData(entityDataList);
@@ -104,6 +101,17 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
}
}
private boolean isEmptyDisplayName(@Nullable Object o) {
if (o == null) {
return true;
} else if (o instanceof String s) {
return s.isEmpty();
} else if (o instanceof JsonElement element) {
return element.isJsonNull() || (element.isJsonPrimitive() && element.getAsJsonPrimitive().getAsString().isEmpty());
}
return false;
}
private void addDisplayVisibilityData(List<EntityData> entityDataList) {
if (alwaysShowOriginalMobName()) {
removeData(displayVisibilityIndex, entityDataList);
@@ -140,10 +148,6 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
return entityDataMappings.get(type.getId());
}
protected @Nullable StoredEntityData storedEntityData(EntityDataHandlerEvent event) {
return tracker(event.user()).entityData(event.entityId());
}
/**
* Maps an entity type to another with extra data.
* Note that both types should be of the same version.
@@ -175,7 +179,7 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
filter().handler((event, data) -> {
EntityDataType type = data.dataType();
if (type == itemType) {
protocol.getItemRewriter().handleItemToClient(event.user(), data.value());
data.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), data.value()));
} else if (type == blockStateType) {
int value = data.value();
data.setValue(protocol.getMappingData().getNewBlockStateId(value));
@@ -227,6 +231,8 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
});
}
// ------------------ Legacy methods
// ONLY TRACKS, DOESN'T REWRITE IDS
protected PacketHandler getTrackerHandler(Type<? extends Number> intType, int typeIndex) {
return wrapper -> {
@@ -242,23 +248,9 @@ public abstract class EntityRewriterBase<C extends ClientboundPacketType, T exte
return getTrackerHandler(Types.VAR_INT, 1);
}
protected PacketHandler getTrackerHandler(EntityType entityType) {
return wrapper -> tracker(wrapper.user()).addEntity(wrapper.get(Types.VAR_INT, 0), entityType);
}
protected PacketHandler getPlayerTrackerHandler() {
return wrapper -> {
final int entityId = wrapper.get(Types.INT, 0);
final EntityTracker tracker = tracker(wrapper.user());
tracker(wrapper.user()).setClientEntityId(entityId);
tracker.addEntity(entityId, tracker.playerType());
};
}
protected PacketHandler getDimensionHandler(int index) {
return wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(this.protocol.getClass());
ClientWorld clientWorld = wrapper.user().storables(this.protocol).clientWorld();
int dimensionId = wrapper.get(Types.INT, index);
if (clientWorld.setEnvironment(dimensionId)) {
tracker(wrapper.user()).clearEntities();
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -208,9 +208,9 @@ public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S
}
@Override
public @Nullable Item handleItemToServer(UserConnection connection, @Nullable final Item item) {
public @Nullable Item handleItemToServer(UserConnection connection, @Nullable Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
item = super.handleItemToServer(connection, item);
if (item.tag() != null) {
Tag originalId = item.tag().remove(nbtTagName("id"));
if (originalId instanceof IntTag) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,7 +17,6 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
@@ -25,6 +24,7 @@ import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.item.Item;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@ import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.entities.storage.EntityObjectData;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.WrappedEntityData;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.ObjectType;
@@ -35,6 +36,7 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -50,7 +52,7 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
}
protected EntityObjectData mapObjectType(ObjectType oldObjectType, ObjectType replacement, int data) {
EntityObjectData entData = new EntityObjectData(protocol, oldObjectType.getType().name(), oldObjectType.getId(), replacement.getId(), data);
EntityObjectData entData = new EntityObjectData(protocol, oldObjectType.getType().name().toLowerCase(Locale.ROOT), oldObjectType.getId(), replacement.getId(), data);
objectTypes.put(oldObjectType, entData);
return entData;
}
@@ -65,7 +67,7 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
public void register() {
map(Types.INT);
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(protocol.getClass());
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
if (clientWorld.setEnvironment(wrapper.get(Types.INT, 0))) {
tracker(wrapper.user()).clearEntities();
}
@@ -82,12 +84,13 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
map(Types.INT); // 2 - Dimension
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(protocol.getClass());
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
clientWorld.setEnvironment(wrapper.get(Types.INT, 1));
final int entityId = wrapper.get(Types.INT, 0);
addTrackedEntity(wrapper, entityId, playerType);
tracker(wrapper.user()).setClientEntityId(entityId);
final EntityTracker tracker = tracker(wrapper.user());
tracker.addEntity(entityId, playerType);
tracker.setClientEntityId(entityId);
});
}
});
@@ -131,13 +134,13 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
return;
}
addTrackedEntity(wrapper, wrapper.get(Types.VAR_INT, 0), type);
tracker(wrapper.user()).addEntity(wrapper.get(Types.VAR_INT, 0), type);
};
}
protected PacketHandler getTrackerAndDataHandler(Type<List<EntityData>> dataType, EntityType entityType) {
return wrapper -> {
addTrackedEntity(wrapper, wrapper.get(Types.VAR_INT, 0), entityType);
tracker(wrapper.user()).addEntity(wrapper.get(Types.VAR_INT, 0), entityType);
List<EntityData> entityDataList = wrapper.get(dataType, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), entityDataList, wrapper.user());
};
@@ -162,11 +165,6 @@ public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T ex
};
}
@Deprecated
protected void addTrackedEntity(PacketWrapper wrapper, int entityId, EntityType type) {
tracker(wrapper.user()).addEntity(entityId, type);
}
@FunctionalInterface
protected interface IdSetter {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,24 +17,22 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.type.Types;
public class SoundRewriter<C extends ClientboundPacketType> extends com.viaversion.viaversion.rewriter.SoundRewriter<C> {
private final BackwardsProtocol<C, ?, ?, ?> protocol;
public SoundRewriter(final BackwardsProtocol<C, ?, ?, ?> protocol) {
public SoundRewriter(final AbstractProtocol<C, ?, ?, ?> protocol) {
super(protocol);
this.protocol = protocol;
}
public void registerNamedSound(final C packetType) {
if (protocol.getMappingData() == null || Mappings.isFullIdentity(protocol.getMappingData().getFullSoundMappings())) {
return;
}
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.STRING); // Sound identifier
getNamedSoundHandler().handle(wrapper);
@@ -42,36 +40,18 @@ public class SoundRewriter<C extends ClientboundPacketType> extends com.viaversi
}
public void registerStopSound(final C packetType) {
protocol.registerClientbound(packetType, wrapper -> getStopSoundHandler().handle(wrapper));
}
public PacketHandler getNamedSoundHandler() {
return wrapper -> {
final String soundId = wrapper.get(Types.STRING, 0);
final String mappedId = protocol.getMappingData().getMappedNamedSound(soundId);
if (mappedId == null) {
return;
}
if (!mappedId.isEmpty()) {
wrapper.set(Types.STRING, 0, mappedId);
} else {
wrapper.cancel();
}
};
}
public PacketHandler getStopSoundHandler() {
return wrapper -> {
if (protocol.getMappingData() == null || Mappings.isFullIdentity(protocol.getMappingData().getFullSoundMappings())) {
return;
}
protocol.registerClientbound(packetType, wrapper -> {
final byte flags = wrapper.passthrough(Types.BYTE);
if ((flags & 0x02) == 0) return; // No sound specified
if ((flags & 0x01) != 0) {
wrapper.passthrough(Types.VAR_INT); // Source
}
if ((flags & 0x02) == 0) return; // No sound specified
final String soundId = wrapper.read(Types.STRING);
final String mappedId = protocol.getMappingData().getMappedNamedSound(soundId);
final String mappedId = protocol.getMappingData().getFullSoundMappings().mappedIdentifier(soundId);
if (mappedId == null) {
// No mapping found
wrapper.write(Types.STRING, soundId);
@@ -84,45 +64,22 @@ public class SoundRewriter<C extends ClientboundPacketType> extends com.viaversi
// Cancel if set to empty
wrapper.cancel();
}
};
});
}
@Override
public void registerSound1_19_3(final C packetType) {
protocol.registerClientbound(packetType, getSoundHandler1_19_3());
}
public PacketHandler getSoundHandler1_19_3() {
public PacketHandler getNamedSoundHandler() {
return wrapper -> {
Holder<SoundEvent> soundEventHolder = wrapper.read(Types.SOUND_EVENT);
if (soundEventHolder.isDirect()) {
wrapper.write(Types.SOUND_EVENT, rewriteSoundEvent(wrapper, soundEventHolder));
final String soundId = wrapper.get(Types.STRING, 0);
final String mappedId = protocol.getMappingData().getFullSoundMappings().mappedIdentifier(soundId);
if (mappedId == null) {
return;
}
final int mappedId = idRewriter.rewrite(soundEventHolder.id());
if (mappedId == -1) {
if (!mappedId.isEmpty()) {
wrapper.set(Types.STRING, 0, mappedId);
} else {
wrapper.cancel();
return;
}
if (mappedId != soundEventHolder.id()) {
soundEventHolder = Holder.of(mappedId);
}
wrapper.write(Types.SOUND_EVENT, soundEventHolder);
};
}
public Holder<SoundEvent> rewriteSoundEvent(final PacketWrapper wrapper, final Holder<SoundEvent> soundEventHolder) {
final SoundEvent soundEvent = soundEventHolder.value();
final String mappedIdentifier = protocol.getMappingData().getMappedNamedSound(soundEvent.identifier());
if (mappedIdentifier != null) {
if (!mappedIdentifier.isEmpty()) {
return Holder.of(soundEvent.withIdentifier(mappedIdentifier));
}
wrapper.cancel();
}
return soundEventHolder;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,6 +33,7 @@ import com.viaversion.viaversion.libs.fastutil.ints.Int2IntMap;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectIterator;
import com.viaversion.viaversion.rewriter.IdRewriteFunction;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.Limit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -195,7 +196,12 @@ public class StructuredEnchantmentRewriter {
}
final Enchantments enchantments = new Enchantments(tag.remove(itemRewriter.nbtTagName("show_" + key.identifier())) != null);
int i = 0;
for (final CompoundTag enchantment : enchantmentsTag) {
if (i++ > 255) {
break;
}
enchantments.add(enchantment.getInt("id"), enchantment.getInt("lvl"));
}
data.set(key, enchantments);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -0,0 +1,103 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.item;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonParser;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.libs.gson.JsonSyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Prevent expensive parsing/toString by checking against cached JsonElement instances, used from 1.14 to 1.20.5.
* <p>
* When using this, be careful not to break caching by modifying the display tag directly.
*/
public final class DataItemWithExtras extends DataItem {
private JsonElement name;
private List<JsonElement> lore;
public DataItemWithExtras(final Item from) {
setIdentifier(from.identifier());
setAmount(from.amount());
setData(from.data());
setTag(from.tag());
if (tag() == null) {
return;
}
final CompoundTag display = tag().getCompoundTag("display");
if (display == null) {
return;
}
final StringTag name = display.getStringTag("Name");
if (name != null) {
this.name = parse(name.getValue());
}
final ListTag<StringTag> lore = display.getListTag("Lore", StringTag.class);
if (lore != null) {
this.lore = new ArrayList<>(lore.size());
for (int i = 0; i < lore.size(); i++) {
this.lore.add(parse(lore.get(i).getValue()));
}
}
}
public @Nullable JsonElement name() {
return name;
}
public @Nullable StringTag rawName() {
if (tag() == null) {
return null;
}
final CompoundTag display = tag().getCompoundTag("display");
return display != null ? display.getStringTag("Name") : null;
}
public @Nullable List<JsonElement> lore() {
return lore;
}
public @Nullable ListTag<StringTag> rawLore() {
if (tag() == null) {
return null;
}
final CompoundTag display = tag().getCompoundTag("display");
return display != null ? display.getListTag("Lore", StringTag.class) : null;
}
private JsonElement parse(final String value) {
try {
return JsonParser.parseString(value);
} catch (final JsonSyntaxException e) {
return new JsonPrimitive(value);
}
}
}
@@ -0,0 +1,38 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.registration;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations;
public final class BackwardsRegistrations {
private static final SharedRegistrations REGISTRATIONS = SharedRegistrations.create();
public static void apply() {
REGISTRATIONS.registrations()
.range(ProtocolVersion.v1_10, ProtocolVersion.v1_19_3, RegistryRegistrations::registerNamedSound1_10)
.since(ProtocolVersion.v1_14, RegistryRegistrations::registerStopSound1_14)
.register();
}
public static SharedRegistrations registrations() {
return REGISTRATIONS;
}
}
@@ -0,0 +1,36 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.registration;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
final class RegistryRegistrations {
static <CU extends ClientboundPacketType> void registerNamedSound1_10(final RegistrationContext<CU, ?> ctx) {
ctx.clientbound(ClientboundPackets1_9_3.CUSTOM_SOUND, new SoundRewriter<>(ctx.protocol())::registerNamedSound, PacketBound.REMOVED_AT_MAX);
}
static <CU extends ClientboundPacketType> void registerStopSound1_14(final RegistrationContext<CU, ?> ctx) {
ctx.clientbound(ClientboundPackets1_14.STOP_SOUND, new SoundRewriter<>(ctx.protocol())::registerStopSound);
}
}
@@ -1,73 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
import com.viaversion.viaversion.api.type.types.version.Types1_21_5;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.RecipeDisplayRewriter1_21_5;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
// To replace if needed:
// ChunkType1_21_5
// RecipeDisplayRewriter
// Types1_21_4
final class BlockItemPacketRewriter1_99 extends BackwardsStructuredItemRewriter<ClientboundPacket1_21_2, ServerboundPacket1_21_4, Protocol1_98To1_99> {
public BlockItemPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
super(protocol, Types1_21_4.ITEM, Types1_21_4.ITEM_ARRAY);
/*super(protocol,
Types1_21_4.ITEM, Types1_21_4.ITEM_ARRAY, Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY,
Types1_21_4.ITEM_COST, Types1_21_4.OPTIONAL_ITEM_COST, Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST
);*/
}
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPacket1_21_2> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21_2.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_2.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_2.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_2.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_2.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_21_5::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_2.BLOCK_ENTITY_DATA);
// registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN);
protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
registerSetPlayerInventory(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets1_21_2.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_2.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
registerContainerClick1_21_5(ServerboundPackets1_21_4.CONTAINER_CLICK);
registerSetCreativeModeSlot1_21_5(ServerboundPackets1_21_4.SET_CREATIVE_MODE_SLOT, Types1_21_5.LENGTH_PREFIXED_ITEM, Types1_21_5.LENGTH_PREFIXED_ITEM); // Change this
final RecipeDisplayRewriter<ClientboundPacket1_21_2> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_2.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_2.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE);
}
}
@@ -0,0 +1,64 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.rewriters.BackwardsStructuredItemRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
// To replace if needed:
// ChunkType1_21_5
// RecipeDisplayRewriter
final class BlockItemPacketRewriter99_1 extends BackwardsStructuredItemRewriter<ClientboundPacket26_1, ServerboundPacket1_21_9, Protocol99_1To98_1> {
public BlockItemPacketRewriter99_1(final Protocol99_1To98_1 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
}
@Override
protected void handleItemDataComponentsToClient(final UserConnection connection, final Item item, final StructuredDataContainer container) {
super.handleItemDataComponentsToClient(connection, item, container);
// downgradeData(item, container); // static import VV method
}
@Override
protected void handleItemDataComponentsToServer(final UserConnection connection, final Item item, final StructuredDataContainer container) {
super.handleItemDataComponentsToServer(connection, item, container);
// upgradeData(item, container); // static import VV method
}
@Override
protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) {
super.restoreBackupData(item, container, customData);
// restore any data if needed here
}
@Override
protected void backupInconvertibleData(final UserConnection connection, final Item item, final StructuredDataContainer dataContainer, final CompoundTag backupTag) {
super.backupInconvertibleData(connection, item, dataContainer, backupTag);
// back up any data if needed here, called before the method below
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,11 +21,11 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
final class ComponentRewriter1_99 extends NBTComponentRewriter<ClientboundPacket1_21_2> {
final class ComponentRewriter99_1 extends NBTComponentRewriter<ClientboundPacket26_1> {
public ComponentRewriter1_99(final BackwardsProtocol<ClientboundPacket1_21_2, ?, ?, ?> protocol) {
public ComponentRewriter99_1(final BackwardsProtocol<ClientboundPacket26_1, ?, ?, ?> protocol) {
super(protocol);
}
@@ -1,91 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
// Replace if needed
// Types1_OLD
// Types1_21_4
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21_2, Protocol1_98To1_99> {
public EntityPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
super(protocol, Types1_21_4.ENTITY_DATA_TYPES.optionalComponentType, Types1_21_4.ENTITY_DATA_TYPES.booleanType);
}
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_21_2.ADD_ENTITY, EntityTypes1_21_4.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, /*Types1_OLD.ENTITY_DATA_LIST, */Types1_21_4.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets1_21_2.PLAYER_ABILITIES);
registerGameEvent(ClientboundPackets1_21_2.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets1_21_2.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_2.RESPAWN);
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
}
@Override
protected void registerRewrites() {
/*filter().handler((event, data) -> {
int id = data.dataType().typeId();
if (id >= ac) {
return;
} else if (id >= ab) {
id--;
}
data.setDataType(Types1_21_4.ENTITY_DATA_TYPES.byId(id));
});*/
registerEntityDataTypeHandler1_20_3(
Types1_21_4.ENTITY_DATA_TYPES.itemType,
Types1_21_4.ENTITY_DATA_TYPES.blockStateType,
Types1_21_4.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_21_4.ENTITY_DATA_TYPES.particleType,
Types1_21_4.ENTITY_DATA_TYPES.particlesType,
Types1_21_4.ENTITY_DATA_TYPES.componentType,
Types1_21_4.ENTITY_DATA_TYPES.optionalComponentType
);
// Remove entity data of new entity type
// filter().type(EntityTypes1_21_4.SNIFFER).removeIndex(newIndex);
}
@Override
public void onMappingDataLoaded() {
// If types changed, uncomment to map them
// mapTypes();
// mapEntityTypeWithData(EntityTypes1_21_4.SNIFFER, EntityTypes1_21_4.RAVAGER).tagName();
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_4.getTypeFromId(type);
}
}
@@ -0,0 +1,75 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.rewriters.EntityRewriter;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
// Replace if needed
// VersionedTypes
final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_1, Protocol99_1To98_1> {
private static final EntityDataTypes26_1 MAPPED_DATA_TYPES = VersionedTypes.V26_1.entityDataTypes;
public EntityPacketRewriter99_1(final Protocol99_1To98_1 protocol) {
super(protocol, MAPPED_DATA_TYPES.optionalComponentType, MAPPED_DATA_TYPES.booleanType);
}
@Override
public void registerPackets() {
}
@Override
protected void registerRewrites() {
dataTypeMapper().register();
/* ... or like this for additions and removals that are not at the very end
dataTypeMapper()
.added(MAPPED_DATA_TYPES.catSoundVariant)
.removed(MAPPED_DATA_TYPES.cowSoundVariant)
.skip(MAPPED_DATA_TYPES.pigSoundVariant) // if neither removed nor added, but the value type has to be changed separately
.register();*/
registerEntityDataTypeHandler1_20_3(
MAPPED_DATA_TYPES.itemType,
MAPPED_DATA_TYPES.blockStateType,
MAPPED_DATA_TYPES.optionalBlockStateType,
MAPPED_DATA_TYPES.particleType,
MAPPED_DATA_TYPES.particlesType,
MAPPED_DATA_TYPES.componentType,
MAPPED_DATA_TYPES.optionalComponentType
);
// Remove entity data of new entity type
// filter().type(EntityTypes1_21_11.SNIFFER).removeIndex(newIndex);
}
@Override
public void onMappingDataLoaded() {
super.onMappingDataLoaded();
// mapEntityTypeWithData(EntityTypes1_21_11.SNIFFER, EntityTypes1_21_11.RAVAGER).tagName();
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_11.getTypeFromId(type);
}
}
@@ -1,146 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_98To1_99, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99
// Protocol1_20_5To1_21 (the ViaVersion protocol class the mappings depend on)
// ClientboundPacket1_21_2
// ServerboundPacket1_21_4
// ClientboundConfigurationPackets1_21
// ServerboundConfigurationPackets1_20_5
// EntityTypes1_21_4 (UNMAPPED type)
// Types1_21_4.PARTICLE
// 1.99, 1.98
final class Protocol1_98To1_99 extends BackwardsProtocol<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_4, ServerboundPacket1_21_4> {
// ViaBackwards uses its own mappings and also needs a translatablerewriter for translation mappings
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("1.99", "1.98", Protocol1_20_5To1_21.class);
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
private final ParticleRewriter<ClientboundPacket1_21_2> particleRewriter = new ParticleRewriter<>(this, Types1_21_4.PARTICLE/*, Types1_OLD.PARTICLE*/);
private final NBTComponentRewriter<ClientboundPacket1_21_2> translatableRewriter = new ComponentRewriter1_99(this);
private final TagRewriter<ClientboundPacket1_21_2> tagRewriter = new TagRewriter<>(this);
public Protocol1_98To1_99() {
super(ClientboundPacket1_21_2.class, ClientboundPacket1_21_2.class, ServerboundPacket1_21_4.class, ServerboundPacket1_21_4.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
tagRewriter.registerGeneric(ClientboundPackets1_21_2.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
final SoundRewriter<ClientboundPacket1_21_2> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND_ENTITY);
soundRewriter.registerStopSound(ClientboundPackets1_21_2.STOP_SOUND);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_2.AWARD_STATS);
//new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
// Registers translatable mappings (missing a whole bunch still)
//translatableRewriter.registerOpenScreen1_14(ClientboundPackets1_21_2.OPEN_SCREEN); // Handled by registerOpenScreen in item rewriters
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_ACTION_BAR_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_TITLE_TEXT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
translatableRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
translatableRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
translatableRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE);
translatableRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
translatableRewriter.registerDisguisedChat(ClientboundPackets1_21_2.DISGUISED_CHAT);
translatableRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_2.PLAYER_CHAT);
translatableRewriter.registerPing();
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_2.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_2(ClientboundPackets1_21_2.EXPLODE);
}
@Override
public void init(final UserConnection user) {
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_21_4.PLAYER));
}
@Override
public BackwardsMappingData getMappingData() {
return MAPPINGS;
}
@Override
public EntityPacketRewriter1_99 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter1_99 getItemRewriter() {
return itemRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_2> getParticleRewriter() {
return particleRewriter;
}
@Override
public NBTComponentRewriter<ClientboundPacket1_21_2> getComponentRewriter() {
return translatableRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21_2> getTagRewriter() {
return tagRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_4, ServerboundPacket1_21_4> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_4.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_4.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
@@ -0,0 +1,156 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viabackwards.protocol.template;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.BackwardsRegistryRewriter;
import com.viaversion.viabackwards.api.rewriters.text.NBTComponentRewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.Protocol1_21_11To26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v26_2to26_3.rewriter.RecipeDisplayRewriter26_3;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.block.BlockRewriter1_21_5;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_21_11To26_1 (the ViaVersion protocol class the mappings depend on)
// ClientboundPacket26_1
// ServerboundPacket1_21_9
// ClientboundConfigurationPackets1_21
// ServerboundConfigurationPackets1_20_5
// EntityTypes1_21_11 (UNMAPPED type)
// VersionedTypes.V26_1
// 99.1, 98.1
final class Protocol99_1To98_1 extends BackwardsProtocol<ClientboundPacket26_1, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket1_21_9> {
// ViaBackwards uses its own mappings and also needs a translatablerewriter for translation mappings
public static final BackwardsMappingData MAPPINGS = new BackwardsMappingData("99.1", "98.1", Protocol1_21_11To26_1.class); // Change the VV (!) protocol class
private final EntityPacketRewriter99_1 entityRewriter = new EntityPacketRewriter99_1(this);
private final BlockItemPacketRewriter99_1 itemRewriter = new BlockItemPacketRewriter99_1(this);
private final ParticleRewriter<ClientboundPacket26_1> particleRewriter = new ParticleRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket26_1> translatableRewriter = new ComponentRewriter99_1(this);
private final TagRewriter<ClientboundPacket26_1> tagRewriter = new TagRewriter<>(this);
private final BackwardsRegistryRewriter registryDataRewriter = new BackwardsRegistryRewriter(this);
private final BlockRewriter<ClientboundPacket26_1> blockRewriter = new BlockRewriter1_21_5<>(this, ChunkType26_1::new);
private final RecipeDisplayRewriter<ClientboundPacket26_1> recipeRewriter = new RecipeDisplayRewriter26_3<>(this);
public Protocol99_1To98_1() {
super(ClientboundPacket26_1.class, ClientboundPacket26_1.class, ServerboundPacket1_21_9.class, ServerboundPacket1_21_9.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
// Remove newly synchronized registries to prevent errors on older clients
//registryDataRewriter.remove("worldgen/block_state_provider");
}
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection);
addItemHasher(connection);
}
// If data beyond the tracker and hasher is required
//@Override
//public ProtocolStorablesBase createStorables() {
// return new ProtocolStorables99_1();
//}
@Override
public BackwardsMappingData getMappingData() {
return MAPPINGS;
}
@Override
public EntityPacketRewriter99_1 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter99_1 getItemRewriter() {
return itemRewriter;
}
@Override
public BlockRewriter<ClientboundPacket26_1> getBlockRewriter() {
return blockRewriter;
}
@Override
public RecipeDisplayRewriter<ClientboundPacket26_1> getRecipeRewriter() {
return recipeRewriter;
}
@Override
public BackwardsRegistryRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket26_1> getParticleRewriter() {
return particleRewriter;
}
@Override
public NBTComponentRewriter<ClientboundPacket26_1> getComponentRewriter() {
return translatableRewriter;
}
@Override
public TagRewriter<ClientboundPacket26_1> getTagRewriter() {
return tagRewriter;
}
@Override
public VersionedTypesHolder types() {
return VersionedTypes.V26_1;
}
@Override
public VersionedTypesHolder mappedTypes() {
return VersionedTypes.V26_1;
}
@Override
protected PacketTypesProvider<ClientboundPacket26_1, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket1_21_9> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets26_1.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets26_1.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class)
);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -57,7 +57,7 @@ public class Protocol1_10To1_9_3 extends BackwardsProtocol<ClientboundPackets1_9
itemRewriter.register();
SoundRewriter<ClientboundPackets1_9_3> soundRewriter = new SoundRewriter<>(this);
registerClientbound(ClientboundPackets1_9_3.CUSTOM_SOUND, new PacketHandlers() {
replaceClientbound(ClientboundPackets1_9_3.CUSTOM_SOUND, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // 0 - Sound name
@@ -70,7 +70,7 @@ public class Protocol1_10To1_9_3 extends BackwardsProtocol<ClientboundPackets1_9
handler(soundRewriter.getNamedSoundHandler());
}
});
registerClientbound(ClientboundPackets1_9_3.SOUND, new PacketHandlers() {
replaceClientbound(ClientboundPackets1_9_3.SOUND, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // 0 - Sound name
@@ -98,8 +98,8 @@ public class Protocol1_10To1_9_3 extends BackwardsProtocol<ClientboundPackets1_9
@Override
public void init(UserConnection user) {
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_10.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_10.EntityType.PLAYER));
user.storables(this).setClientWorld(new ClientWorld());
}
@Override
@@ -116,9 +116,4 @@ public class Protocol1_10To1_9_3 extends BackwardsProtocol<ClientboundPackets1_9
public BlockItemPacketRewriter1_10 getItemRewriter() {
return itemRewriter;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -50,7 +50,7 @@ public class BlockItemPacketRewriter1_10 extends LegacyBlockItemRewriter<Clientb
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_9_3.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
Chunk chunk = wrapper.passthrough(type);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +29,6 @@ import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_9;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import java.util.List;
@@ -80,7 +79,7 @@ public class EntityPacketRewriter1_10 extends LegacyEntityRewriter<ClientboundPa
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_9.ENTITY_DATA_LIST); // 12 - Entity data
map(Types.ENTITY_DATA_LIST1_9); // 12 - Entity data
// Track entity
handler(getTrackerHandler(Types.UNSIGNED_BYTE, 0));
@@ -93,7 +92,7 @@ public class EntityPacketRewriter1_10 extends LegacyEntityRewriter<ClientboundPa
return;
}
List<EntityData> entityDataList = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
List<EntityData> entityDataList = wrapper.get(Types.ENTITY_DATA_LIST1_9, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), entityDataList, wrapper.user());
EntityReplacement entityReplacement = entityDataForType(type);
@@ -122,14 +121,14 @@ public class EntityPacketRewriter1_10 extends LegacyEntityRewriter<ClientboundPa
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
map(Types.ENTITY_DATA_LIST1_9); // 7 - Entity data list
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types.ENTITY_DATA_LIST1_9, EntityTypes1_11.EntityType.PLAYER));
}
});
registerRemoveEntities(ClientboundPackets1_9_3.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types1_9.ENTITY_DATA_LIST);
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types.ENTITY_DATA_LIST1_9);
}
@Override
@@ -158,6 +157,9 @@ public class EntityPacketRewriter1_10 extends LegacyEntityRewriter<ClientboundPa
}
});
// Added index from incorrect entity data hierarchy, where potions add to item entities
filter().type(EntityTypes1_10.EntityType.POTION).addIndex(6);
// Handle the missing NoGravity tag for every entity data
filter().removeIndex(5);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -39,8 +39,8 @@ public class Protocol1_11_1To1_11 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_11.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_11.EntityType.PLAYER));
user.storables(this).setClientWorld(new ClientWorld());
}
@Override
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,7 +24,6 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
public class EntityPacketRewriter1_11_1 extends LegacyEntityRewriter<ClientboundPackets1_9_3, Protocol1_11_1To1_11> {
@@ -72,13 +71,13 @@ public class EntityPacketRewriter1_11_1 extends LegacyEntityRewriter<Clientbound
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_9.ENTITY_DATA_LIST); // 12 - Entity data
map(Types.ENTITY_DATA_LIST1_9); // 12 - Entity data
// Track entity
handler(getTrackerHandler());
// Rewrite entity type / data
handler(getMobSpawnRewriter1_11(Types1_9.ENTITY_DATA_LIST));
handler(getMobSpawnRewriter1_11(Types.ENTITY_DATA_LIST1_9));
}
});
@@ -96,14 +95,14 @@ public class EntityPacketRewriter1_11_1 extends LegacyEntityRewriter<Clientbound
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
map(Types.ENTITY_DATA_LIST1_9); // 7 - Entity data list
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types.ENTITY_DATA_LIST1_9, EntityTypes1_11.EntityType.PLAYER));
}
});
registerRemoveEntities(ClientboundPackets1_9_3.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types1_9.ENTITY_DATA_LIST);
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types.ENTITY_DATA_LIST1_9);
}
@Override
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,8 +23,6 @@ import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
import com.viaversion.viabackwards.protocol.v1_11_1to1_11.Protocol1_11_1To1_11;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
@@ -73,7 +71,7 @@ public class ItemPacketRewriter1_11_1 extends LegacyBlockItemRewriter<Clientboun
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
item = super.handleItemToServer(connection, item);
enchantmentRewriter.handleToServer(item);
return item;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@ package com.viaversion.viabackwards.protocol.v1_11to1_10;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.text.JsonNBTComponentRewriter;
import com.viaversion.viabackwards.protocol.v1_11to1_10.rewriter.BlockItemPacketRewriter1_11;
import com.viaversion.viabackwards.protocol.v1_11to1_10.rewriter.EntityPacketRewriter1_11;
@@ -51,18 +50,14 @@ public class Protocol1_11To1_10 extends BackwardsProtocol<ClientboundPackets1_9_
itemRewriter.register();
PlayerPacketRewriter1_11.register(this);
SoundRewriter<ClientboundPackets1_9_3> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerNamedSound(ClientboundPackets1_9_3.CUSTOM_SOUND);
soundRewriter.registerSound(ClientboundPackets1_9_3.SOUND);
componentRewriter = new JsonNBTComponentRewriter<>(this, ComponentRewriterBase.ReadType.JSON);
componentRewriter.registerComponentPacket(ClientboundPackets1_9_3.CHAT);
}
@Override
public void init(UserConnection user) {
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_11.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_11.EntityType.PLAYER));
user.storables(this).setClientWorld(new ClientWorld());
if (!user.has(WindowTracker.class)) {
user.put(new WindowTracker());
@@ -84,12 +79,8 @@ public class Protocol1_11To1_10 extends BackwardsProtocol<ClientboundPackets1_9_
return itemRewriter;
}
@Override
public JsonNBTComponentRewriter<ClientboundPackets1_9_3> getComponentRewriter() {
return componentRewriter;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -22,27 +22,39 @@ import com.viaversion.viaversion.libs.fastutil.ints.Int2IntOpenHashMap;
public class SplashPotionMappings1_10 {
private static final Int2IntMap DATA = new Int2IntOpenHashMap(14, 0.99F);
private static final Int2IntMap DATA = new Int2IntOpenHashMap(26, 0.99F);
static {
DATA.defaultReturnValue(-1);
DATA.put(2039713, 5); // night vision
DATA.put(8356754, 7); // invisibility
DATA.put(2293580, 9); // jump boost
DATA.put(14981690, 12); // fire resistance
DATA.put(8171462, 14); // swiftness
DATA.put(5926017, 17); // slowness
DATA.put(3035801, 19); // water breathing
DATA.put(16262179, 21); // instant health
DATA.put(4393481, 23); // instant damage
DATA.put(5149489, 25); // poison
DATA.put(13458603, 28); // regeneration
DATA.put(9643043, 31); // strength
DATA.put(4738376, 34); // weakness
DATA.put(3381504, 36); // luck
DATA.put(0x1F1FA1, 5); // night vision
DATA.put(0xC2FF66, 5); // night vision 1.19.4
DATA.put(0x7F8392, 7); // invisibility
DATA.put(0xF6F6F6, 7); // invisibility 1.19.4
DATA.put(0x22FF4C, 9); // jump boost
DATA.put(0xFDFF84, 9); // jump boost 1.19.4
DATA.put(0xE49A3A, 12); // fire resistance
DATA.put(0xFF9900, 12); // fire resistance 1.19.4
DATA.put(0x7CAFC6, 14); // swiftness
DATA.put(0x33EBFF, 14); // swiftness 1.19.4
DATA.put(0x5A6C81, 17); // slowness
DATA.put(0x8BAFE0, 17); // slowness 1.19.4
DATA.put(0x2E5299, 19); // water breathing
DATA.put(0x98DAC0, 19); // water breathing 1.19.4
DATA.put(0xF82423, 21); // instant health
DATA.put(0x430A09, 23); // instant damage
DATA.put(0xA9656A, 23); // instant damage 1.19.4
DATA.put(0x4E9331, 25); // poison
DATA.put(0x87A363, 25); // poison 1.19.4
DATA.put(0xCD5CAB, 28); // regeneration
DATA.put(0x932423, 31); // strength
DATA.put(0xFFC700, 31); // strength 1.19.4
DATA.put(0x484D48, 34); // weakness
DATA.put(0x339900, 36); // luck
DATA.put(0x59C106, 36); // luck 1.19.4
}
public static int getOldData(int data) {
return DATA.get(data);
// newer servers send as ARGB
return DATA.get(data & 0xFFFFFF);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,6 +18,8 @@
package com.viaversion.viabackwards.protocol.v1_11to1_10.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.api.data.MappedLegacyBlockItem;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
@@ -26,7 +28,7 @@ import com.viaversion.viabackwards.protocol.v1_11to1_10.storage.ChestedHorseStor
import com.viaversion.viabackwards.protocol.v1_11to1_10.storage.WindowTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
@@ -35,12 +37,9 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_9_3;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.protocols.v1_10to1_11.data.EntityMappings1_11;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
import com.viaversion.viaversion.util.IdAndData;
import java.util.Arrays;
import java.util.Optional;
@@ -147,7 +146,7 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11To1_10.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment()); // Use the 1.10 Chunk type since nothing changed.
Chunk chunk = wrapper.passthrough(type);
@@ -252,7 +251,7 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
@Override
protected void registerRewrites() {
// Handle spawner block entity (map to itself with custom handler)
MappedLegacyBlockItem data = itemReplacements.computeIfAbsent(IdAndData.toRawData(52), s -> new MappedLegacyBlockItem(52));
MappedLegacyBlockItem data = blockReplacements.computeIfAbsent(compress(52, -1), s -> new MappedLegacyBlockItem(52, (short) -1, null, MappedLegacyBlockItem.Type.BLOCK));
data.setBlockEntityHandler((b, tag) -> EntityMappings1_11.toClientSpawner(tag, true));
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName());
@@ -280,7 +279,7 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
item = super.handleItemToServer(connection, item);
CompoundTag tag = item.tag();
if (tag == null) return item;
@@ -295,9 +294,9 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
private boolean isLlama(UserConnection user) {
WindowTracker tracker = user.get(WindowTracker.class);
if (tracker.getInventory() != null && tracker.getInventory().equals("EntityHorse")) {
EntityTracker entTracker = user.getEntityTracker(Protocol1_11To1_10.class);
StoredEntityData entityData = entTracker.entityData(tracker.getEntityId());
return entityData != null && entityData.type().is(EntityTypes1_11.EntityType.LLAMA);
EntityTracker entTracker = user.getEntityTracker(protocol);
TrackedEntity entityData = entTracker.entity(tracker.getEntityId());
return entityData != null && entityData.entityType().is(EntityTypes1_11.EntityType.LLAMA);
}
return false;
}
@@ -305,8 +304,8 @@ public class BlockItemPacketRewriter1_11 extends LegacyBlockItemRewriter<Clientb
private Optional<ChestedHorseStorage> getChestedHorse(UserConnection user) {
WindowTracker tracker = user.get(WindowTracker.class);
if (tracker.getInventory() != null && tracker.getInventory().equals("EntityHorse")) {
EntityTracker entTracker = user.getEntityTracker(Protocol1_11To1_10.class);
StoredEntityData entityData = entTracker.entityData(tracker.getEntityId());
EntityTracker entTracker = user.getEntityTracker(protocol);
TrackedEntity entityData = entTracker.entity(tracker.getEntityId());
if (entityData != null)
return Optional.of(entityData.get(ChestedHorseStorage.class));
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,14 +23,12 @@ import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.v1_11to1_10.Protocol1_11To1_10;
import com.viaversion.viabackwards.protocol.v1_11to1_10.data.SplashPotionMappings1_10;
import com.viaversion.viabackwards.protocol.v1_11to1_10.storage.ChestedHorseStorage;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_9;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import java.util.List;
@@ -104,17 +102,17 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_9.ENTITY_DATA_LIST); // 12 - Entity data
map(Types.ENTITY_DATA_LIST1_9); // 12 - Entity data
// Track entity
handler(getTrackerHandler(Types.UNSIGNED_BYTE, 0));
// Rewrite entity type / data
handler(getMobSpawnRewriter(Types1_9.ENTITY_DATA_LIST));
handler(getMobSpawnRewriter(Types.ENTITY_DATA_LIST1_9));
// Sub 1.11 clients will error if the list is empty
handler(wrapper -> {
List<EntityData> entityDataList = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
List<EntityData> entityDataList = wrapper.get(Types.ENTITY_DATA_LIST1_9, 0);
if (entityDataList.isEmpty()) {
entityDataList.add(new EntityData(0, EntityDataTypes1_9.BYTE, (byte) 0));
}
@@ -136,12 +134,12 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
map(Types.ENTITY_DATA_LIST1_9); // 7 - Entity data list
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_11.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types.ENTITY_DATA_LIST1_9, EntityTypes1_11.EntityType.PLAYER));
handler(wrapper -> {
// Sub 1.11 clients will cry if the list is empty
List<EntityData> entityDataList = wrapper.get(Types1_9.ENTITY_DATA_LIST, 0);
List<EntityData> entityDataList = wrapper.get(Types.ENTITY_DATA_LIST1_9, 0);
if (entityDataList.isEmpty()) {
entityDataList.add(new EntityData(0, EntityDataTypes1_9.BYTE, (byte) 0));
}
@@ -150,7 +148,7 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
});
registerRemoveEntities(ClientboundPackets1_9_3.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types1_9.ENTITY_DATA_LIST);
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types.ENTITY_DATA_LIST1_9);
protocol.registerClientbound(ClientboundPackets1_9_3.ENTITY_EVENT, new PacketHandlers() {
@Override
@@ -260,9 +258,9 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
// Handle horse flags
filter().type(EntityTypes1_11.EntityType.ABSTRACT_HORSE).index(13).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
byte b = (byte) data.getValue();
if (entityData.has(ChestedHorseStorage.class) && entityData.get(ChestedHorseStorage.class).isChested()) {
final ChestedHorseStorage chestedHorseStorage = event.trackedEntity().get(ChestedHorseStorage.class);
if (chestedHorseStorage != null && chestedHorseStorage.isChested()) {
b |= 0x08; // Chested
data.setValue(b);
}
@@ -270,9 +268,8 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
// Create chested horse storage
filter().type(EntityTypes1_11.EntityType.CHESTED_HORSE).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
if (!entityData.has(ChestedHorseStorage.class)) {
entityData.put(new ChestedHorseStorage());
if (!event.trackedEntity().has(ChestedHorseStorage.class)) {
event.trackedEntity().put(new ChestedHorseStorage());
}
});
@@ -281,8 +278,7 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
// Handle chested horse
filter().type(EntityTypes1_11.EntityType.CHESTED_HORSE).index(15).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
ChestedHorseStorage storage = entityData.get(ChestedHorseStorage.class);
ChestedHorseStorage storage = event.trackedEntity().get(ChestedHorseStorage.class);
boolean b = (boolean) data.getValue();
storage.setChested(b);
event.cancel();
@@ -290,8 +286,7 @@ public class EntityPacketRewriter1_11 extends LegacyEntityRewriter<ClientboundPa
// Get rid of Liama entity data
filter().type(EntityTypes1_11.EntityType.LLAMA).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
ChestedHorseStorage storage = entityData.get(ChestedHorseStorage.class);
ChestedHorseStorage storage = event.trackedEntity().get(ChestedHorseStorage.class);
int index = event.index();
// Store them for later (:
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,7 +18,9 @@
package com.viaversion.viabackwards.protocol.v1_11to1_10.storage;
public class ChestedHorseStorage {
import com.viaversion.viaversion.api.connection.StorableObject;
public final class ChestedHorseStorage implements StorableObject {
private boolean chested;
private int liamaStrength;
private int liamaCarpetColor = -1;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,7 +21,6 @@ package com.viaversion.viabackwards.protocol.v1_12_2to1_12_1;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.protocol.v1_12_2to1_12_1.storage.KeepAliveTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ServerboundPackets1_12_1;
@@ -34,32 +33,20 @@ public class Protocol1_12_2To1_12_1 extends BackwardsProtocol<ClientboundPackets
@Override
protected void registerPackets() {
registerClientbound(ClientboundPackets1_12_1.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
Long keepAlive = packetWrapper.read(Types.LONG);
packetWrapper.user().get(KeepAliveTracker.class).setKeepAlive(keepAlive);
packetWrapper.write(Types.VAR_INT, keepAlive.hashCode());
});
}
registerClientbound(ClientboundPackets1_12_1.KEEP_ALIVE, wrapper -> {
long keepAlive = wrapper.read(Types.LONG);
int id = wrapper.user().get(KeepAliveTracker.class).track(keepAlive);
wrapper.write(Types.VAR_INT, id);
});
registerServerbound(ServerboundPackets1_12_1.KEEP_ALIVE, new PacketHandlers() {
@Override
public void register() {
handler(packetWrapper -> {
int keepAlive = packetWrapper.read(Types.VAR_INT);
long realKeepAlive = packetWrapper.user().get(KeepAliveTracker.class).getKeepAlive();
if (keepAlive != Long.hashCode(realKeepAlive)) {
packetWrapper.cancel(); // Wrong data, cancel packet
return;
}
packetWrapper.write(Types.LONG, realKeepAlive);
// Reset KeepAliveTracker (to prevent sending same valid value in a row causing a timeout)
packetWrapper.user().get(KeepAliveTracker.class).setKeepAlive(Integer.MAX_VALUE);
});
registerServerbound(ServerboundPackets1_12_1.KEEP_ALIVE, wrapper -> {
int keepAlive = wrapper.read(Types.VAR_INT);
Long realKeepAlive = wrapper.user().get(KeepAliveTracker.class).consume(keepAlive);
if (realKeepAlive == null) {
wrapper.cancel(); // stale/bad
return;
}
wrapper.write(Types.LONG, realKeepAlive);
});
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,20 +19,22 @@
package com.viaversion.viabackwards.protocol.v1_12_2to1_12_1.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public class KeepAliveTracker implements StorableObject {
private long keepAlive = Integer.MAX_VALUE;
public long getKeepAlive() {
return keepAlive;
private final Map<Integer, Long> pending = new HashMap<>();
private int nextId;
public int track(long original) {
int id = nextId++;
pending.put(id, original);
return id;
}
public void setKeepAlive(long keepAlive) {
this.keepAlive = keepAlive;
}
@Override
public String toString() {
return "KeepAliveTracker{" + "keepAlive=" + keepAlive + '}';
public @Nullable Long consume(int id) {
return pending.remove(id);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,11 +20,11 @@ package com.viaversion.viabackwards.protocol.v1_12to1_11_1;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.storage.ShoulderTracker;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.rewriter.BlockItemPacketRewriter1_12;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.rewriter.ComponentRewriter1_12;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.rewriter.EntityPacketRewriter1_12;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.rewriter.SoundPacketRewriter1_12;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.storage.ShoulderTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_12;
@@ -50,8 +50,8 @@ public class Protocol1_12To1_11_1 extends BackwardsProtocol<ClientboundPackets1_
@Override
protected void registerPackets() {
itemRewriter.register();
entityRewriter.register();
super.registerPackets();
componentRewriter.registerComponentPacket(ClientboundPackets1_12.CHAT);
new SoundPacketRewriter1_12(this).register();
@@ -71,8 +71,8 @@ public class Protocol1_12To1_11_1 extends BackwardsProtocol<ClientboundPackets1_
@Override
public void init(UserConnection user) {
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, EntityTypes1_12.EntityType.PLAYER));
user.addClientWorld(this.getClass(), new ClientWorld());
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_12.EntityType.PLAYER));
user.storables(this).setClientWorld(new ClientWorld());
user.put(new ShoulderTracker(user));
}
@@ -92,12 +92,8 @@ public class Protocol1_12To1_11_1 extends BackwardsProtocol<ClientboundPackets1_
return itemRewriter;
}
@Override
public ComponentRewriter1_12 getComponentRewriter() {
return componentRewriter;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,7 +18,13 @@
package com.viaversion.viabackwards.protocol.v1_12to1_11_1.rewriter;
import com.google.common.primitives.Ints;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.LongArrayTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.Protocol1_12To1_11_1;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.data.MapColorMappings1_11_1;
@@ -30,18 +36,14 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_9_3;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.LongArrayTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.packet.ClientboundPackets1_12;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.packet.ServerboundPackets1_12;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
import java.util.Iterator;
import java.util.Map;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.SerializerVersion;
import java.util.Iterator;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<ClientboundPackets1_12, ServerboundPackets1_9_3, Protocol1_12To1_11_1> {
@@ -114,7 +116,7 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
PacketWrapper confirm = wrapper.create(ServerboundPackets1_12.CONTAINER_ACK);
confirm.write(Types.BYTE, wrapper.get(Types.BYTE, 0));
confirm.write(Types.SHORT, wrapper.get(Types.SHORT, 1));
confirm.write(Types.BOOLEAN, false); // Success - not used
confirm.write(Types.BOOLEAN, true); // Success - not used
wrapper.sendToServer(Protocol1_12To1_11_1.class);
wrapper.cancel();
@@ -131,7 +133,7 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_12.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_12To1_11_1.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment()); // Use the 1.9.4 Chunk type since nothing changed.
Chunk chunk = wrapper.passthrough(type);
@@ -230,6 +232,30 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
backupTag.put(entry.getKey(), fromLongArrayTag(tag));
iterator.remove();
hasLongArrayTag = true;
} else if (entry.getValue() instanceof ListTag<?> tag) {
if (tag.getElementType() == LongArrayTag.class) {
// Lists can't hold mixed tag types, so the whole list has to be removed
ListTag<IntArrayTag> intArrays = new ListTag<>(IntArrayTag.class);
for (Tag longArrayTag : tag) {
intArrays.add(fromLongArrayTag((LongArrayTag) longArrayTag));
}
backupTag.put(entry.getKey(), intArrays);
iterator.remove();
hasLongArrayTag = true;
} else if (tag.getElementType() == CompoundTag.class) {
// Backed up by list index
CompoundTag listBackupTag = new CompoundTag();
for (int i = 0; i < tag.size(); i++) {
CompoundTag nestedBackupTag = new CompoundTag();
if (handleNbtToClient((CompoundTag) tag.get(i), nestedBackupTag)) {
listBackupTag.put(Integer.toString(i), nestedBackupTag);
}
}
if (!listBackupTag.isEmpty()) {
backupTag.put(entry.getKey(), listBackupTag);
hasLongArrayTag = true;
}
}
}
}
return hasLongArrayTag;
@@ -238,7 +264,7 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
@Override
public @Nullable Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
item = super.handleItemToServer(connection, item);
if (item.tag() != null) {
if (item.tag().remove("Via|LongArrayTags") instanceof CompoundTag tag) {
@@ -252,11 +278,33 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
private void handleNbtToServer(CompoundTag compoundTag, CompoundTag backupTag) {
// Restore the removed long array tags
for (Map.Entry<String, Tag> entry : backupTag) {
if (entry.getValue() instanceof CompoundTag) {
CompoundTag nestedTag = compoundTag.getCompoundTag(entry.getKey());
handleNbtToServer(nestedTag, (CompoundTag) entry.getValue());
} else {
compoundTag.put(entry.getKey(), fromIntArrayTag((IntArrayTag) entry.getValue()));
if (entry.getValue() instanceof CompoundTag nestedBackupTag) {
Tag tag = compoundTag.get(entry.getKey());
if (tag instanceof CompoundTag nestedTag) {
handleNbtToServer(nestedTag, nestedBackupTag);
} else if (tag instanceof ListTag<?> listTag) {
handleListToServer(listTag, nestedBackupTag);
}
} else if (entry.getValue() instanceof IntArrayTag intArrayTag) {
compoundTag.put(entry.getKey(), fromIntArrayTag(intArrayTag));
} else if (entry.getValue() instanceof ListTag<?> intArrays) {
ListTag<LongArrayTag> longArrays = new ListTag<>(LongArrayTag.class);
for (Tag intArrayTag : intArrays) {
if (intArrayTag instanceof IntArrayTag) {
longArrays.add(fromIntArrayTag((IntArrayTag) intArrayTag));
}
}
compoundTag.put(entry.getKey(), longArrays);
}
}
}
private void handleListToServer(ListTag<?> listTag, CompoundTag backupTag) {
for (Map.Entry<String, Tag> entry : backupTag) {
Integer index = Ints.tryParse(entry.getKey());
if (index != null && index >= 0 && index < listTag.size()
&& listTag.get(index) instanceof CompoundTag nestedTag && entry.getValue() instanceof CompoundTag nestedBackupTag) {
handleNbtToServer(nestedTag, nestedBackupTag);
}
}
}
@@ -275,7 +323,7 @@ public class BlockItemPacketRewriter1_12 extends LegacyBlockItemRewriter<Clientb
private LongArrayTag fromIntArrayTag(IntArrayTag tag) {
long[] longArray = new long[tag.length() / 2];
int[] intArray = tag.getValue();
for (int i = 0, j = 0; i < intArray.length; i += 2, j++) {
for (int i = 0, j = 0; j < longArray.length; i += 2, j++) {
longArray[j] = (long) intArray[i] << 32 | ((long) intArray[i + 1] & 0xFFFFFFFFL);
}
return new LongArrayTag(longArray);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,7 +23,6 @@ import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.Protocol1_12To1_11_1;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.storage.ParrotStorage;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.storage.ShoulderTracker;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_12;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
@@ -31,8 +30,6 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_12;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.packet.ClientboundPackets1_12;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
@@ -84,13 +81,13 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
map(Types.SHORT); // 9 - Velocity X
map(Types.SHORT); // 10 - Velocity Y
map(Types.SHORT); // 11 - Velocity Z
map(Types1_12.ENTITY_DATA_LIST, Types1_9.ENTITY_DATA_LIST); // 12 - Entity data
map(Types.ENTITY_DATA_LIST1_12, Types.ENTITY_DATA_LIST1_9); // 12 - Entity data
// Track entity
handler(getTrackerHandler());
// Rewrite entity type / data
handler(getMobSpawnRewriter1_11(Types1_9.ENTITY_DATA_LIST));
handler(getMobSpawnRewriter1_11(Types.ENTITY_DATA_LIST1_9));
}
});
@@ -106,9 +103,9 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
map(Types.DOUBLE); // 4 - Z
map(Types.BYTE); // 5 - Yaw
map(Types.BYTE); // 6 - Pitch
map(Types1_12.ENTITY_DATA_LIST, Types1_9.ENTITY_DATA_LIST); // 7 - Entity data list
map(Types.ENTITY_DATA_LIST1_12, Types.ENTITY_DATA_LIST1_9); // 7 - Entity data list
handler(getTrackerAndDataHandler(Types1_9.ENTITY_DATA_LIST, EntityTypes1_12.EntityType.PLAYER));
handler(getTrackerAndDataHandler(Types.ENTITY_DATA_LIST1_9, EntityTypes1_12.EntityType.PLAYER));
}
});
@@ -120,7 +117,7 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
map(Types.INT); // 2 - Dimension
handler(getDimensionHandler(1));
handler(getPlayerTrackerHandler());
handler(playerTrackerHandler());
handler(wrapper -> {
ShoulderTracker tracker = wrapper.user().get(ShoulderTracker.class);
@@ -142,7 +139,7 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
registerRespawn(ClientboundPackets1_12.RESPAWN);
registerRemoveEntities(ClientboundPackets1_12.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_12.SET_ENTITY_DATA, Types1_12.ENTITY_DATA_LIST, Types1_9.ENTITY_DATA_LIST);
registerSetEntityData(ClientboundPackets1_12.SET_ENTITY_DATA, Types.ENTITY_DATA_LIST1_12, Types.ENTITY_DATA_LIST1_9);
protocol.registerClientbound(ClientboundPackets1_12.UPDATE_ATTRIBUTES, new PacketHandlers() {
@Override
@@ -210,16 +207,14 @@ public class EntityPacketRewriter1_12 extends LegacyEntityRewriter<ClientboundPa
// Create Parrot storage
filter().type(EntityTypes1_12.EntityType.PARROT).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
if (!entityData.has(ParrotStorage.class)) {
entityData.put(new ParrotStorage());
if (!event.trackedEntity().has(ParrotStorage.class)) {
event.trackedEntity().put(new ParrotStorage());
}
});
// Parrot remove animal entity data
filter().type(EntityTypes1_12.EntityType.PARROT).cancel(12); // Is baby
filter().type(EntityTypes1_12.EntityType.PARROT).index(13).handler((event, data) -> {
StoredEntityData entityData = storedEntityData(event);
ParrotStorage storage = entityData.get(ParrotStorage.class);
ParrotStorage storage = event.trackedEntity().get(ParrotStorage.class);
boolean isSitting = (((byte) data.getValue()) & 0x01) == 0x01;
boolean isTamed = (((byte) data.getValue()) & 0x04) == 0x04;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2025 ViaVersion and contributors
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,7 +21,6 @@ package com.viaversion.viabackwards.protocol.v1_12to1_11_1.rewriter;
import com.viaversion.viabackwards.api.rewriters.LegacySoundRewriter;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.Protocol1_12To1_11_1;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.packet.ClientboundPackets1_12;
@@ -33,20 +32,7 @@ public class SoundPacketRewriter1_12 extends LegacySoundRewriter<Protocol1_12To1
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_12.CUSTOM_SOUND, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // 0 - Sound name
map(Types.VAR_INT); // 1 - Sound Category
map(Types.INT); // 2 - x
map(Types.INT); // 3 - y
map(Types.INT); // 4 - z
map(Types.FLOAT); // 5 - Volume
map(Types.FLOAT); // 6 - Pitch
}
});
protocol.registerClientbound(ClientboundPackets1_12.SOUND, new PacketHandlers() {
protocol.replaceClientbound(ClientboundPackets1_12.SOUND, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // 0 - Sound name
Loaded 100 of 399 files, more files were not shown because too many files have changed in this diff. Show more