Compare commits

..
536 Commits
Author SHA1 Message Date
Nassim Jahnke 132cf1d6e1 5.0.0 Release 2024-06-16 14:02:32 +02:00
Nassim Jahnke 5f57041413 Fix item data handling order 2024-06-16 11:05:50 +02:00
Nassim Jahnke f91a25cba7 Make sure we have block mappings before trying to apply them 2024-06-16 10:22:37 +02:00
Nassim Jahnke 547041cb62 Merge branch 'refs/heads/dev' into preview 2024-06-15 16:11:26 +02:00
Pantera (Mad_Daniel) b7af3b7d8e Fix player head in 1.20.2->1.20 (#786) 2024-06-15 15:10:20 +02:00
Nassim Jahnke bb927b31f7 Some fixups
Informative commit message I know
2024-06-14 00:58:32 +02:00
EnZaXD eceda8ac58 Add remaining item array type in BlockItemPacketRewriter1_13 (#784) 2024-06-13 18:42:17 +02:00
Nassim Jahnke 65d829065a Read proper sound event type in 1.20.5->1.20.3 2024-06-13 18:33:43 +02:00
Nassim Jahnke 0b38dc18a5 Remove snapshot from version 2024-06-12 18:10:36 +02:00
Nassim Jahnke 4b58f6d154 1.21-rc1 2024-06-12 18:08:23 +02:00
Nassim Jahnke 6d8fee053d 1.21-pre3 2024-06-12 18:08:23 +02:00
Nassim Jahnke 335415efd7 1.21-pre2 2024-06-12 18:08:23 +02:00
Nassim Jahnke 59f7ce339e Remove jukebox_playable 2024-06-12 18:08:22 +02:00
Nassim Jahnke a9b9c48b26 Handle item changes in show item text components 2024-06-12 18:08:22 +02:00
Nassim Jahnke 8fb814ef11 Handle chat and horse container changes 2024-06-12 18:08:22 +02:00
Nassim Jahnke 9873f279a4 Bump version 2024-06-12 18:08:22 +02:00
Nassim Jahnke ab1467dba5 Handle jukebox song level event 2024-06-12 18:08:21 +02:00
Nassim Jahnke 3749a5d5da Update data component ids 2024-06-12 18:08:21 +02:00
Nassim Jahnke 6f8da18f65 24w21b, mostly 2024-06-12 18:08:21 +02:00
Nassim Jahnke 1a24ce6d87 24w20a 2024-06-12 18:08:21 +02:00
Nassim Jahnke e9d142e2ec Rebase onto 5.0.0 2024-06-12 18:08:20 +02:00
Nassim Jahnke 218b2abe45 24w19a 2024-06-12 18:08:20 +02:00
Nassim Jahnke 263790e9f6 24w18a 2024-06-12 18:08:20 +02:00
EnZaXD 094bfe34c6 Use trade list rewriter functions (#782) 2024-06-11 15:10:22 +02:00
Nassim Jahnke bfbc086f44 Revert "Send registry data before finish configuration in 1.20.5->1.20.3 (#778)"
This reverts commit e93e30c235.
2024-06-08 20:09:10 +02:00
EnZaXD 7bd43e0234 Use TagRewriter#registerGeneric in 1.20.3->1.20.2 (#779) 2024-06-07 18:38:29 +02:00
EnZaXD e93e30c235 Send registry data before finish configuration in 1.20.5->1.20.3 (#778) 2024-06-07 18:19:49 +02:00
Nassim Jahnke 2f5fbd93ea Make items in 1.20.5+ non null 2024-06-07 13:52:45 +02:00
EnZaXD f86fdd1eb4 Update VV API usage (#776) 2024-06-06 11:09:39 +02:00
Nassim Jahnke 993608b4b4 Also apply MC-68487 workaround to items 2024-06-06 10:56:43 +02:00
EnZaXD a786152dfc Handle UPDATE_LISTED state in 1.19.3->1.19.1 (#775) 2024-06-05 09:24:47 +02:00
EnZaXD 89caecef4f Ignore errors in 1.14->1.13.2 lore tag conversion (#773) 2024-06-04 12:42:43 +02:00
EnZaXD 6058763489 Don't publish extra modules (#772) 2024-06-03 20:31:54 +02:00
EnZaXD 8a675923d1 Emulate recovery compass using lodestone compass in 1.19->1.18.2 (#770) 2024-06-03 09:49:39 +02:00
EnZaXD 3370383481 Add firework flight length fix from VV (#769) 2024-06-02 09:04:17 +02:00
Nassim Jahnke 449ddd1de7 Update Gradle wrapper 2024-06-01 17:10:40 +02:00
Nassim Jahnke 9efc2e630f Update publication metadata 2024-05-30 22:37:44 +02:00
Nassim Jahnke 5849bf06e6 Move Bungee and Sponge modules to separate plugins 2024-05-30 22:21:49 +02:00
EnZaXD 1c45e41934 Fix horse/llama's armor/carpet not visible in 1.20.5->.3 (#765) 2024-05-30 15:47:06 +02:00
Nassim Jahnke bc3d6b952f Resend damageable item on cancelled block break in 1.11->1.10
The client assumes durability changes, so we have to resend the item
2024-05-30 15:42:07 +02:00
EnZaXD b53c0aeb9b Handle block state particles when identifier is used in 1.20.5->.3 (#764) 2024-05-30 10:45:02 +02:00
EnZaXD 3511ba3c67 [ci skip] Replace GitHub link to hangar/viaversion.com sub link (#766) 2024-05-30 10:43:20 +02:00
EnZaXD 1bf5f7408b Add missing translation mappings and component rewriter (#761) 2024-05-28 10:52:08 +02:00
EnZaXD 9e63243003 Make TranslatableRewriter usable in other projects as well (#762) 2024-05-27 19:37:57 +02:00
RK_01 98fad11060 Update Via API usage (#760) 2024-05-27 13:35:14 +02:00
Nassim Jahnke fe4986b042 Fix sniffer entity data removal
Fixes #757
2024-05-22 10:11:09 +02:00
Nassim Jahnke 0618037a0e Rename Position 2024-05-21 13:12:18 +02:00
Nassim Jahnke d7f550fc4f Remove empty item tags
Fixes #752
2024-05-21 11:20:55 +02:00
Nassim Jahnke a9ed655d95 Add extra slot to horse inventories
Fixes #754
2024-05-21 10:36:02 +02:00
EnZaXD 6e75026681 Add config option to suppress emulation warnings (#751) 2024-05-19 09:27:22 +02:00
EnZaXD f9890db702 Use legacy chunk rewriter functions (#750) 2024-05-15 17:27:43 +02:00
EnZaXD dd4ab8082e Update data class names to indicate target version (#749) 2024-05-15 11:16:50 +02:00
EnZaXD f949fd658a [ci skip] Add J17 note to README as well (#748) 2024-05-14 22:20:07 +02:00
EnZaXD 8f92d55747 Update Via API usage (#747) 2024-05-14 20:48:49 +02:00
EnZaXD 4d6c6a2da1 Fix wrong Protocol1_8To1_9#STRING_TO_JSON usages in 1.12->1.11.1 (#746) 2024-05-14 20:48:19 +02:00
Nassim Jahnke 903a49b96a Apply IJ code reformat 2024-05-14 20:48:17 +02:00
FlorianMichael b85046f11d Rework logging inside protocols and rewriters 2024-05-14 20:48:07 +02:00
FlorianMichael 264cce865b Rename data, protocol and mapping classes
Syncs names with https://github.com/ViaVersion/ViaVersion/commit/a2b7fc82e2bc3a30823812da3c4d478f467a5411
2024-05-14 20:47:58 +02:00
FlorianMichael c27f720316 Update Via API usage
Question to EntityPacketRewriter1_16_2: is it intended that the LOGIN handler doesn't copy the written dimensions tag or was that just forgotten?
2024-05-14 20:47:43 +02:00
Nassim Jahnke a946632e8b Lots of renames 2024-05-14 20:47:40 +02:00
Nassim Jahnke 5e7371d39b Start working on 5.0.0 2024-05-11 15:01:36 +02:00
EnZaXD abb1803aaf Cache dimensions without namespace in 1.19->1.18.2 (#744) 2024-05-10 21:47:45 +02:00
Nassim Jahnke e45a95c6ec Bump version to 4.10.3-SNAPSHOT 2024-05-10 21:47:35 +02:00
Nassim Jahnke 17bda0fc29 4.10.2 Release 2024-05-10 13:24:40 +02:00
EnZaXD 1a22b371cd Handle bad heightmaps in 1.17->1.16.4 (#743) 2024-05-09 21:56:14 +02:00
EnZaXD 6292c5a5a5 Use backup tag remove method when rewriting trade list (#742) 2024-05-09 20:55:31 +02:00
Nassim Jahnke 6b616d8b07 Fixup banner handling 2024-05-09 19:44:03 +02:00
Nassim Jahnke fd43ca56d7 Properly write properties 2024-05-09 18:04:13 +02:00
Nassim Jahnke 91193cf602 Handle player head block entities
Fixes #741
2024-05-09 17:22:31 +02:00
EnZaXD 1680f9985d [ci skip] Use login/status packet enums in older protocols (#740) 2024-05-09 09:25:17 +02:00
EnZaXD e8602adf5b Fix red nether brick name in 1.11->1.10 (#739) 2024-05-07 19:35:18 +02:00
EnZaXD 7f0982e59c Fix item mappings with explicit data (0) (#738) 2024-05-07 18:54:38 +02:00
Nassim Jahnke 072b59060c Don't write null criteria for unknown advancements 2024-05-07 17:07:13 +02:00
EnZaXD 633b4b393b Remove alpha channel from particle colors in 1.20.5->.3 (#737) 2024-05-06 09:50:33 +02:00
Nassim Jahnke 34101ea8b8 4.10.1 Release
Definitely the first time I made this commit
2024-05-05 16:53:56 +02:00
Nassim Jahnke 093328db11 Handle missing mappings 2024-05-05 16:53:36 +02:00
Nassim Jahnke 5bd8786737 Update entity mapping usage 2024-05-05 12:22:17 +02:00
EnZaXD fedda03062 Use TagUtil#removeNamespaced in 1.19.4->.3 (#735) 2024-05-02 16:07:22 +02:00
EnZaXD 99f6356230 Make chat_types handling in 1.19 protocols optional (#733) 2024-05-02 15:59:51 +02:00
EnZaXD 9b8e65c59d Implement handleTranslate() for tags in TranslatableRewriter (#734) 2024-05-02 15:28:40 +02:00
Nassim JahnkeandKrakenied bd2eb42374 Add advancement criteria if possible in 1.20.2->1.20
Fixes #616

Co-authored-by: Krakenied <Krakenied1@gmail.com>
2024-05-01 11:31:03 +02:00
Nassim Jahnke e9db3f040f Check both namespaced and implicit key when replacing registries 2024-05-01 10:35:48 +02:00
Nassim Jahnke ce0e01abec Auto: Update copyright headers 2024-04-30 22:29:02 +02:00
Nassim Jahnke 025603027e Remove default components from trade list 2024-04-30 22:29:02 +02:00
EnZaXD 67ae00faeb Add support for different mapping types with same id (#731) 2024-04-30 18:29:45 +02:00
Nassim Jahnke 325e3f92ed Remove 1.19.4 registries without namespace as well 2024-04-29 23:12:37 +02:00
Nassim Jahnke 42897030f7 Fix entity effect reading below 1.20.2
Fixes #3811
2024-04-28 11:39:43 +02:00
Nassim Jahnke ddeaf921be Register listeners a tick later
Because 1.8 has task registration order reverse???
Fixes #730
2024-04-28 11:35:51 +02:00
Nassim Jahnke 06c30c2838 Add paperweight-mappings-namespace attribute 2024-04-28 03:52:25 +02:00
Gero bf7ed14506 Fix remapping of 1.20.5 CLICK_WINDOW_BUTTON 2024-04-27 21:31:49 +02:00
Gero c4d0c7ab8f Bump to 4.10.1-SNAPSHOT 2024-04-27 21:31:41 +02:00
Nassim Jahnke f1f337af27 Bump VV dependency 2024-04-26 15:25:19 +02:00
Nassim Jahnke e37fea42d4 4.10.0 Release 2024-04-26 15:15:57 +02:00
FlorianMichael 78a667c5b9 Add constructors to LegacyBlockItemRewriter to define item types 2024-04-26 15:15:24 +02:00
Nassim Jahnke 27dd2e39bd Merge branch 'refs/heads/dev' into preview
# Conflicts:
#	common/src/main/java/com/viaversion/viabackwards/api/data/BackwardsMappings.java
2024-04-26 14:32:00 +02:00
Nassim Jahnke b3115ea71d Fix some namespace parsing issues 2024-04-26 13:31:14 +02:00
Nassim Jahnke be742fc493 Fix 1.20.3->1.20.2 cloud particle handling 2024-04-26 13:19:09 +02:00
EnZaXD 100febf575 Rework legacy item/block mappings format (#728) 2024-04-26 09:18:42 +02:00
Nassim Jahnke cddf30b60f Read normal byte array type for cookie packet 2024-04-25 19:11:19 +02:00
EnZaXD c4c15fb047 Add EntityRewriterBase#getDisplayVisibilityMetaValue (#725) 2024-04-23 22:18:58 +02:00
EnZaXD ab11527c86 Reuse existing logger getter in BackwardsMappings (#726) 2024-04-23 22:18:45 +02:00
Nassim Jahnke 1d3a444fe0 Update version 2024-04-23 17:02:21 +02:00
Nassim Jahnke 82bb374edc Update version references 2024-04-23 11:26:31 +02:00
Nassim Jahnke a4147a24f1 Merge branch 'refs/heads/dev' into preview 2024-04-23 11:00:24 +02:00
EnZaXD 87f2a6ba7b Add mob spawn rewriter function for pre 1.11 (#724) 2024-04-23 10:45:12 +02:00
EnZaXD 948c615622 Replace LegacyEntityRewriter#getObjectTypeFromId with existing method (#723) 2024-04-22 23:30:15 +02:00
Nassim Jahnke 0996fc9270 Merge branch 'refs/heads/dev' into preview
# Conflicts:
#	common/src/main/java/com/viaversion/viabackwards/api/rewriters/EntityRewriterBase.java
#	common/src/main/java/com/viaversion/viabackwards/protocol/protocol1_20_3to1_20_5/rewriter/BlockItemPacketRewriter1_20_5.java
2024-04-21 23:43:33 +02:00
Nassim Jahnke 0cd46fdac9 Also to component rewriter methods 2024-04-21 23:37:00 +02:00
Nassim Jahnke 2a4bfb936f Add UserConnection param to item rewriter methods 2024-04-21 22:48:56 +02:00
Nassim Jahnke 3b9b3ab257 Use getFullItemMappings 2024-04-21 20:50:04 +02:00
FlorianMichael e52210a674 Update mappings 2024-04-21 10:11:17 +02:00
Nassim Jahnke 11286b2162 Fall back to keys without namespace in registry data 2024-04-20 12:13:06 +02:00
Gero 471d4acf20 Add missing dust_color_transition data remapping (changed in 24w03a) 2024-04-19 16:54:52 +02:00
Gero e5fff8fabc 1.20.5-rc2 2024-04-19 16:54:10 +02:00
Nassim Jahnke 23955e5385 Update particle format in biome registry data 2024-04-18 19:16:42 +02:00
Nassim Jahnke bf635cc6c5 1.20.5-rc1 2024-04-18 16:30:58 +02:00
Nassim Jahnke 5a49413dbc Merge branch 'refs/heads/dev' into preview 2024-04-18 16:26:20 +02:00
Nassim Jahnke c64e9acf35 Override getTagRewriter methods 2024-04-18 16:26:03 +02:00
Nassim Jahnke 00f773d150 Merge branch 'refs/heads/master' into dev 2024-04-18 16:19:39 +02:00
EnZaXD 1ac504afb9 Use correct constructor in MappedLegacyBlockItem (#721) 2024-04-17 08:46:48 +02:00
EnZaXD 09eda34051 Use VVs IdAndData class for block id conversions (#719) 2024-04-16 21:05:45 +02:00
EnZaXD 9cf5f98ed1 Replace incoming/outgoing usages with client/server bound (#720) 2024-04-16 21:00:20 +02:00
Nassim Jahnke 1e8cf198e7 Update missed call 2024-04-15 17:29:22 +02:00
Nassim Jahnke caa28df36d 1.20.5-pre2 2024-04-15 17:17:19 +02:00
Nassim Jahnke d2edf3fbfe 1.20.5-pre1 2024-04-10 17:41:19 +02:00
Nassim Jahnke 68807be880 Track banner patterns 2024-04-09 13:18:40 +02:00
Nassim Jahnke 7d6c330fa3 Handle entity effect particle color 2024-04-08 15:05:01 +02:00
Nassim Jahnke 3ea95a0d78 Update authors 2024-04-07 20:44:24 +02:00
FlorianMichael fe708ba0eb Fix chat command handling 2024-04-07 19:58:44 +02:00
Nassim Jahnke fccd5b3f3b Fix trade list handling 2024-04-07 13:41:51 +02:00
Nassim Jahnke 9f652ad24a Update VV usage 2024-04-06 21:33:41 +02:00
Nassim Jahnke f7dad9b5d7 Add StructuredEnchantmentRewriter, update translation mappings 2024-04-06 21:30:19 +02:00
Nassim Jahnke 1507f788ec 24w14a 2024-04-06 21:28:59 +02:00
Nassim Jahnke 41b04f9902 24w13a 2024-04-06 21:28:59 +02:00
Nassim Jahnke 9beaf71196 Handle new argument types 2024-04-06 21:28:59 +02:00
Nassim Jahnke 0c7aa1d037 Update mappings 2024-04-06 21:28:59 +02:00
Nassim Jahnke 7a7d2f1fa1 Handle lore and name in StructuredItemRewriter 2024-04-06 21:28:56 +02:00
Nassim Jahnke 37711d0079 Set rewritten item in metadata rewriter 2024-04-06 21:28:21 +02:00
Nassim Jahnke e1f2f151c9 24w11a 2024-04-06 21:28:21 +02:00
Nassim Jahnke a453163822 Some 24w10a changes 2024-04-06 21:28:21 +02:00
EnZaXD 1647b18233 Override nbtTagName() correctly (#717) 2024-04-05 20:36:03 +02:00
vadage c7dc80b71b Support config loading from input stream (#718) 2024-04-05 20:32:47 +02:00
EnZaXD 39d3265463 Update VV ItemRewriter API Usage (#716) 2024-04-04 09:48:19 +02:00
Nassim Jahnke 2b953556ec Update VV API usage 2024-04-01 14:20:15 +02:00
EnZaXD 4e5b6fe876 Fix minor inconsistencies in older protocols (#714) 2024-04-01 13:01:07 +02:00
EnZaXD 0e74527342 Update Via API usage (#713) 2024-03-31 15:14:33 +02:00
EnZaXD 75fddd0fb9 Allow platforms to disable dummy enchantment in LegacyEnchantmentRewriter (#710) 2024-03-28 14:32:13 +01:00
EnZaXD 0aacfe3bcb Add item handler methods to LegacyEnchantmentRewriter (#709) 2024-03-28 11:22:34 +01:00
EnZaXD 4547d5c702 Move methods in LegacyBlockItemRewriter and expose handleChunk method (#707) 2024-03-27 20:15:57 +01:00
EnZaXD b438484dc7 Keep original item data in LegacyBlockItemRewriter (#706) 2024-03-27 17:04:50 +01:00
EnZaXD ed52ef21ee Add calculation methods for block id and data (#704) 2024-03-27 16:49:14 +01:00
EnZaXD 9d1a5a05f5 Expose EntityRewriterBase#alwaysShowOriginalMobName (#705) 2024-03-27 16:48:35 +01:00
EnZaXD 4e856ef396 Various API changes to LegacyBlockItemRewriter (#703) 2024-03-27 13:27:19 +01:00
EnZaXD 082cc010b2 Update Via API usage (#702) 2024-03-24 22:10:06 +01:00
EnZaXD 59a621315b Allow platforms to use BackwardsMappingDataLoader (#701) 2024-03-24 12:14:51 +01:00
EnZaXD d8b7e7d9ff Update mapping data loader (#700) 2024-03-24 11:46:08 +01:00
Nassim Jahnke 51561d143c Merge branch 'master' into dev
# Conflicts:
#	.github/workflows/publish.yml
2024-03-22 20:55:44 +01:00
Nassim Jahnke 2ffa852c92 Update build dependencies 2024-03-22 20:48:31 +01:00
Nassim Jahnke ac86d891fe Check if id is present in EnchantmentRewriter
Closes #699
2024-03-17 19:58:05 +01:00
Nassim Jahnke 9d8aa9a232 Update mappings 2024-03-17 16:29:32 +01:00
Nassim Jahnke f3b26c5aa5 Fix 1.20.2->1.20 entity sound reading
Fixes ViaVersion/ViaVersion#3744
2024-03-14 14:41:49 +01:00
Nassim Jahnke d96cef7134 Merge branch 'master' into dev 2024-03-09 13:09:17 +01:00
Nassim Jahnke ced1a65230 Replace some generic CompoundTag get usages 2024-03-09 13:08:36 +01:00
Nassim Jahnke 6ad1dc4195 Merge branch 'master' into dev
# Conflicts:
#	gradle.properties
#	gradle/libs.versions.toml
2024-03-07 13:51:41 +01:00
Nassim Jahnke c6ea04fd33 Update ViaNBT 2024-03-07 13:37:42 +01:00
Nassim Jahnke 79a2881a02 4.9.2 Release 2024-03-05 17:51:04 +01:00
Nassim Jahnke 64e68830bc Create FUNDING.yml 2024-03-04 17:32:32 +01:00
EnZaXD ab742c794f Update description included in platforms (#694) 2024-03-04 17:26:59 +01:00
Nassim Jahnke 39e9d6dd04 Use new SoundEvent type 2024-03-01 14:23:13 +01:00
Nassim Jahnke 445d798a17 Partially implement mapped item handling 2024-02-29 20:30:46 +01:00
Nassim Jahnke 66896d2027 Update version 2024-02-29 14:28:48 +01:00
Nassim Jahnke 05b1a6bacd Start working on 24w09a 2024-02-29 12:41:39 +01:00
EnZaXD bf3834ab21 Tidy up fabric.mod.json file of fabric platform (#695) 2024-02-29 12:25:31 +01:00
EnZaXD 2f60c79ed8 Use equals for legacy custom payload channel handlers (#693) 2024-02-29 12:09:50 +01:00
EnZaXD 5bb3e8a1fc paste.gg -> mclo.gs (#689) 2024-02-21 16:13:12 +01:00
Nassim Jahnke 8f417b6caa Rename methods once again 2024-02-14 19:27:40 +01:00
Nassim Jahnke 96d6c0697e Fix compilation 2024-02-14 18:15:41 +01:00
Nassim Jahnke c112044b5a 24w07a 2024-02-14 17:39:31 +01:00
Nassim Jahnke 45c44c8f7e Update VV usage 2024-02-14 11:13:58 +01:00
Nassim Jahnke 5a3a82a83d Update VV usage 2024-02-13 19:03:56 +01:00
Nassim Jahnke bc03235f42 Merge branch 'master' into dev
# Conflicts:
#	common/src/main/java/com/viaversion/viabackwards/protocol/protocol1_16_4to1_17/packets/EntityPackets1_17.java
2024-02-12 11:08:17 +01:00
Nassim Jahnke 073488abcf Update template 2024-02-12 11:03:39 +01:00
Nassim Jahnke b60464296b Small cleanups 2024-02-12 11:02:55 +01:00
Nassim Jahnke 9241213fb5 Replace tag instanceof/unchecked casts with helper methods 2024-02-11 10:42:44 +01:00
Nassim Jahnke e9c3889c82 Add editorconfig 2024-02-11 10:39:06 +01:00
Nassim Jahnke f90861dbce Remap breeze wind charge 2024-02-08 16:19:17 +01:00
Nassim Jahnke 06f07d2b2c 24w06a 2024-02-07 19:07:34 +01:00
Nassim Jahnke fa1c3e1520 24w05b 2024-02-01 17:53:18 +01:00
EnZaXD dca8ecf1db Fix notes color from note block being wrong in 1.13->1.12 (#680)
Closes https://github.com/ViaVersion/ViaBackwards/issues/679
2024-02-01 16:28:40 +01:00
Nassim Jahnke 680d0642c9 Merge branch 'master' into dev
# Conflicts:
#	common/src/main/java/com/viaversion/viabackwards/protocol/protocol1_20_2to1_20_3/rewriter/BlockItemPacketRewriter1_20_3.java
2024-01-31 22:58:51 +01:00
Nassim Jahnke 170e5f224f Fix writable book handling in 1.16->1.15 2024-01-31 22:58:11 +01:00
Nassim Jahnke f6def0c97c 24w05a (mostly) 2024-01-31 18:06:46 +01:00
EnZaXD 4375a259dd Fix 1.17.1 -> 1.18 mappings loading (#676)
Closes https://github.com/ViaVersion/ViaBackwards/issues/568
2024-01-29 20:30:59 +01:00
Nassim Jahnke b3b4d0f618 Merge branch 'master' into dev
# Conflicts:
#	common/src/main/java/com/viaversion/viabackwards/protocol/protocol1_20_2to1_20_3/rewriter/BlockItemPacketRewriter1_20_3.java
2024-01-29 17:33:42 +01:00
Nassim Jahnke 8fc82cd331 Update book conversion error logging 2024-01-29 17:33:08 +01:00
EnZaXD de21548a8e Clean up more item type usage in ItemRewriter (#675) 2024-01-29 17:29:17 +01:00
Nassim Jahnke 8759f059b7 Ignore errors in book conversion 2024-01-29 10:17:50 +01:00
Nassim Jahnke 1f3555df4a Put books through component conversion in 1.20.3->1.20.2 2024-01-27 21:04:32 +01:00
Nassim Jahnke 9abfdfb8f9 Include config packets in Protocol generic types 2024-01-26 16:23:17 +01:00
Nassim Jahnke 8c2f80a632 Fix missed type removal from last commit 2024-01-26 14:38:55 +01:00
Nassim Jahnke 3e89641448 24w04a 2024-01-24 20:23:29 +01:00
Nassim Jahnke a2ddcae076 Merge branch 'master' into dev
# Conflicts:
#	.github/workflows/gradle.yml
2024-01-24 17:51:31 +01:00
Kichura b40f77fed3 Update JDK to 17, setup-java to v4 (#671) 2024-01-20 21:19:36 +01:00
Nassim Jahnke 8ffbc7047f Add cookie handling, TransferProvider for other platforms 2024-01-20 10:26:56 +01:00
Nassim Jahnke e6814a13a9 24w03b (probably) 2024-01-18 16:34:00 +01:00
Kichura 9fd0df824f Update supported Velocity version to 3.3 (#666) 2024-01-14 10:02:16 +01:00
EnZaXD 6b1f913b91 Fix VV API usage (#664) 2024-01-13 09:54:39 +01:00
Nassim Jahnke de42850dd1 Merge branch 'master' into dev
# Conflicts:
#	template/src/main/java/com/viaversion/viabackwards/template/protocol/rewriter/EntityPacketRewriter1_99.java
2024-01-12 10:33:40 +01:00
Nassim Jahnke 88df61605b Update VV usage 2024-01-09 20:59:26 +01:00
Nassim Jahnke 6c2d43d7f9 Handle 1.20->1.20.2 tags 2024-01-09 17:19:19 +01:00
Nassim Jahnke 62765d03ce Merge remote-tracking branch 'origin/master' into dev 2024-01-04 17:51:18 +01:00
Nassim Jahnke 2889daed61 Update license header 2024-01-01 12:38:33 +01:00
Nassim Jahnke 651bf052fc Update ViaNBT 2023-12-31 14:04:57 +01:00
Nassim Jahnke 59660a5bdc Merge branch 'master' into dev 2023-12-27 19:48:40 +01:00
Kichura fa18a572c0 Update setup-java to v4, Fix friendly names in CI steps (#660) 2023-12-27 19:47:31 +01:00
Nassim Jahnke 83fa0c613f Update copyright profile 2023-12-27 17:51:16 +01:00
Nassim Jahnke 5334f77d49 Finish up things 2023-12-27 17:30:47 +01:00
Nassim Jahnke 96293e6e66 Start working on mcstructs usage (missing TranslatableRewriter1_16) 2023-12-27 00:24:56 +01:00
Nassim Jahnke 19ec92c261 Merge remote-tracking branch 'origin/master' into dev 2023-12-26 21:51:03 +01:00
Nassim Jahnke 65faeb8574 Fix 1.20.3->1.20.2 configuration resource pack id 2023-12-26 21:49:34 +01:00
Nassim Jahnke 6ad4a29d30 Allow specifying unmapped data in legacy mappings 2023-12-20 12:10:15 +01:00
Nassim Jahnke ba725df33e 23w51b 2023-12-18 19:50:25 +01:00
Nassim Jahnke 4fe53f5ab8 Update the bane of my existence 2023-12-13 22:45:23 +01:00
Nassim Jahnke a390990178 Read correct method type in update score
Fixes #650
2023-12-13 12:04:43 +01:00
Nassim Jahnke e020dd69ef Fix tab complete tooltip reading in old versions
Fixes #648
2023-12-11 11:27:52 +01:00
Nassim Jahnke b09950dc64 Update Via usage 2023-12-10 12:15:35 +01:00
Nassim Jahnke 7b8fd2b061 Fix 1.17->1.16 map data type reading
Fixes #646
2023-12-09 14:59:43 +01:00
Nassim Jahnke 2d57e8c212 Clone tag instead of abusing tag conversion 2023-12-08 21:06:30 +01:00
Camden Cove dcc3824a8c Fix 1.13.1->1.13 item type in some cases (#645) 2023-12-08 12:05:52 +01:00
EnZaXD 2dd19c778b Handle chunk loading game state in 1.20.3 -> 1.20.2 (#643) 2023-12-08 09:37:20 +01:00
Nassim Jahnke e24a170e77 Fix reset score reading 2023-12-07 23:17:55 +01:00
Nassim Jahnke 3a69dda548 Bump version to 4.9.2-SNAPSHOT 2023-12-07 23:17:36 +01:00
Nassim Jahnke 77ecda3977 4.9.1 Release 2023-12-07 11:19:36 +01:00
Nassim Jahnke c44bc88d2d Convert chat type in disguised chat packet 2023-12-07 10:11:18 +01:00
Nassim Jahnke deede5347e Fix 1.13 map data type
Fixes #641
2023-12-07 09:54:30 +01:00
Nassim Jahnke 255536e9d0 Handle tags packet 2023-12-06 09:47:11 +01:00
Nassim Jahnke 8a2c18863c Fix map marker reading 2023-12-05 22:23:48 +01:00
Nassim Jahnke 375bb5a1b9 Bump version to 4.9.1-SNAPSHOT 2023-12-05 22:18:32 +01:00
Nassim Jahnke c739b54403 4.9.0 Release 2023-12-04 10:14:06 +01:00
Nassim Jahnke a0388cf541 Merge branch 'master' into dev 2023-12-04 10:13:46 +01:00
RK_01 3dd6e5043e Change gamemode data type in JOIN_GAME handlers (#639) 2023-12-03 18:35:47 +01:00
Nassim JahnkeandEnZaXD d30766a17a Fix ordering issue in login ack send on the server
Fixes 1.20.2+ Fabric servers with Fabric API

Co-authored-by: EnZaXD <60033407+FlorianMichael@users.noreply.github.com>
2023-11-30 18:39:41 +01:00
Nassim Jahnke f556a29d38 1.20.3-rc1 2023-11-30 17:13:05 +01:00
Nassim Jahnke 8a19fbdead Update translation mappings 2023-11-30 15:54:54 +01:00
Nassim Jahnke d4011f3646 1.20.3-pre3 2023-11-27 17:12:42 +01:00
EnZaXD 2bd687b19d Implemented ViaVersion's SignableCommandArgumentsProvider (#633) 2023-11-26 15:34:55 +01:00
Nassim Jahnke 4f4bff6898 Update mappings 2023-11-21 07:36:29 +01:00
Nassim Jahnke adac67b85c Handle new resource pack actions 2023-11-21 07:13:37 +01:00
Nassim Jahnke 0949ff4ba9 1.20.3-pre1 (maybe) 2023-11-20 19:09:05 +01:00
Nassim Jahnke 8f5683f764 23w46a (mostly) 2023-11-19 16:48:24 +01:00
Drex 995c0bf4c3 Implement keep blocks explosion types (#632) 2023-11-19 16:19:40 +01:00
Nassim Jahnke 0f77acdc9f Remove todos 2023-11-09 18:00:08 +10:00
Nassim Jahnke ac5fbdd7f4 Allow null mapped entity name 2023-11-09 17:58:10 +10:00
Nassim Jahnke fb7cd2d9e3 23w45a 2023-11-09 17:57:28 +10:00
Nassim Jahnke 5284a581b3 Handle new 1.20.2 map markers 2023-11-08 11:55:03 +10:00
Nassim Jahnke 8eca6bf0b2 Improve Gradle setup
Don't build full platform jars to reduce build time
2023-11-06 14:45:30 +10:00
Nassim Jahnke c13a89a29c Update Gradle wrapper 2023-11-05 11:56:20 +10:00
Nassim Jahnke bce716caa4 Don't expect enables features to always be sent
The client defaults to the vanilla registry, so it doesn't need to be sent
2023-11-05 11:50:33 +10:00
Nassim Jahnke 71f08b9e4e Add 1.20.3 translations, fix unlit bulb mappings 2023-10-26 17:44:17 +10:00
Nassim Jahnke 59fc7f6a1a 23w43a 2023-10-26 13:13:23 +10:00
RK_01 232180ee61 Fix identifier handling in old protocols (#624) 2023-10-24 09:55:13 +10:00
EnZaXD cfb97e1abe Mention ViaVersion addon in "Known issues" (#623) 2023-10-24 09:54:30 +10:00
RK_01 48907be813 Implement support for chat signing (#621) 2023-10-22 19:51:00 +10:00
EnZaXD ff87b1dc92 1.13.2 -> 1.14: Change bamboo mapping (#622) 2023-10-22 12:36:21 +10:00
Nassim Jahnke e68ddf42b0 Update VV usage 2023-10-21 13:41:39 +10:00
Nassim Jahnke 8a9d4bd971 Update VV usage 2023-10-20 12:46:29 +10:00
Nassim Jahnke 7f85d074af Update VV usage 2023-10-19 21:31:00 +10:00
Nassim Jahnke 4cd65dd956 23w42a (if the ci manages to find VV) 2023-10-19 11:50:31 +10:00
Nassim Jahnke 719bb11938 Update TranslatableRewriter 2023-10-18 14:56:44 +10:00
Дмитрий e419831e8a Big Dripleaf mappings change (#614) 2023-10-18 11:48:45 +10:00
Kichura d121745a0f Update Fabric dependencies (#605) 2023-10-16 15:17:17 +10:00
Nassim Jahnke 65158455cc Fix early sending of resource pack
Fixes #3476
2023-10-15 18:12:39 +10:00
Nassim Jahnke 0912e33358 Merge pull request #611 from SplotyCode/fix/scoreboatd 2023-10-13 21:20:00 +10:00
David Scandurra 02f595b109 ChatUtil: Append unwritten formatting in prefix mode 2023-10-12 23:03:18 +02:00
Nassim Jahnke f78d166acf 23w41a (probably) 2023-10-12 01:53:44 +10:00
Nassim Jahnke 2e0acf169b Actually track 1.20.2 entities
Fixes #609, #597
2023-10-11 16:43:32 +10:00
EnZaXD aa1f38674d Fix platform loading (#604) 2023-10-08 19:33:00 +10:00
Nassim Jahnke 9e883faa78 Update nbt lib usage 2023-10-08 18:56:56 +10:00
EnZaXD e27930b1d7 Allow platform implementation to define config path (#603) 2023-10-08 17:20:01 +10:00
Nassim Jahnke d46eb8719a Fix it again 2023-10-08 15:26:37 +10:00
EnZaXD d092c98897 Fix ViaBackwards#init previous platform check (#602) 2023-10-08 15:10:35 +10:00
EnZaXD 75680296e8 Updated Via API usage (#601) 2023-10-08 14:51:49 +10:00
EnZaXD 80696a1273 [ci skip] Note smithing table as not usable for <1.19.4 clients (#600) 2023-10-08 02:18:34 +00:00
Nassim Jahnke 54330702b1 23w40a 2023-10-06 22:36:03 +10:00
Nassim Jahnke f923648fe8 4.8.1 Release 2023-10-03 20:58:18 +10:00
Nassim Jahnke 92c160c43a Fix trade list sending
Forgot to remove cancellation from initial configuration testing
Fixes #594
2023-09-28 11:19:36 +10:00
Nassim Jahnke cc7df5a4fc Fix serverbound beacon secondary effect 2023-09-28 09:36:41 +10:00
Nassim Jahnke 8e6727c350 Handle changed custom potion effects tag 2023-09-27 14:58:03 +10:00
Nassim Jahnke e73eeeb434 Update branch check again 2023-09-26 10:48:42 +10:00
Brokkonaut 96650decae Fix packet id of player velocity packets (#593) 2023-09-26 10:47:57 +10:00
Nassim Jahnke 1d35b1cdb2 [ci skip] Fix branch check in publishing 2023-09-26 00:24:36 +10:00
Nassim Jahnke c6711919b1 Add separate client and server state handling 2023-09-25 18:34:03 +10:00
Nassim Jahnke 67f7a66ca5 Fix 1.20.2->1.20 if run on the backend 2023-09-25 10:54:52 +10:00
Nassim Jahnke 4cba8072c4 Fix implementation version 2023-09-24 23:56:29 +10:00
Nassim Jahnke cfbe287361 Bump version to 4.8.1-SNAPSHOT 2023-09-24 23:55:25 +10:00
Nassim Jahnke f254869c66 4.8.0 Release 2023-09-21 10:35:54 +10:00
Nassim Jahnke 57ca5f1bf5 Fix particle handling 2023-09-21 10:35:42 +10:00
Nassim Jahnke b69ebe6657 Send the config ack packet 2023-09-19 13:25:25 +10:00
Nassim Jahnke ea2fac0788 Handle configuration start
TODO: Check whether all the necessary data for the join game packet is always expected by the client or if we need to cache it from the initial login
2023-09-19 13:20:19 +10:00
Nassim Jahnke 2b2384acc1 Remove new trim patterns in 1.20->1.19
Fixes #570
2023-09-15 18:13:12 +10:00
SplotyCode 643c6b18dd Fix scoreboard component coversion (#586) 2023-09-08 12:22:16 +10:00
Nassim Jahnke 80438807cc 1.20.2-pre2 2023-09-08 09:33:31 +10:00
Nassim Jahnke 2f373adad4 [ci skip] Update Blossom 2023-09-06 11:30:10 +10:00
Nassim Jahnke e2546b8471 1.20.2-pre1 2023-09-06 00:59:17 +10:00
Nassim Jahnke 88fd52ac6e [ci skip] Update Gradle wrapper and checkout actions 2023-09-05 21:29:01 +10:00
Nassim Jahnke c13c3f17fc Fix scoreboard objective reading 2023-08-31 11:48:48 +10:00
Nassim Jahnke 3b9354c4f6 23w35a (untested) 2023-08-31 00:53:48 +10:00
Nassim Jahnke 83636ecf51 Fix 1.16->1.15 hover components in books
Fixes #572
2023-08-27 18:52:43 +10:00
Nassim Jahnke 082b61a956 [ci skip] Update Hangar publish plugin 2023-08-26 20:05:17 +10:00
Nassim Jahnke 108e96ec6d Move world data tracker into first join game handler 2023-08-18 01:36:37 +10:00
Nassim Jahnke 6dd5cb20d9 23w33a 2023-08-18 01:32:50 +10:00
EnZaXD 2a2a0d8a72 Adde1.9 protocols from ViaVersion to ViaBackwards (#580) 2023-08-14 11:06:59 +10:00
Nassim Jahnke 9c68b30865 Merge remote-tracking branch 'origin/master' into dev
# Conflicts:
#	.github/workflows/gradle.yml
2023-08-14 10:15:19 +10:00
EnZaXD e0b7426dc9 Remove unused chat-types setting from config.yml (#579) 2023-08-14 10:04:02 +10:00
EnZaXD 43e2b242c4 Fix 1.19.4 -> 1.19.3 precipitation reading (#578) 2023-08-14 10:02:52 +10:00
Nassim Jahnke 567725d996 Update README 2023-08-11 21:36:20 +10:00
Nassim Jahnke 4fa985f131 Also publish dev branch builds to Hangar 2023-08-11 20:34:24 +10:00
Nassim Jahnke 2e8d6bcc9f Include link to commit in autopublished changelog 2023-08-11 16:26:17 +10:00
Nassim Jahnke 95e3446e8c Add mappings for changed block states and sounds 2023-08-11 16:08:10 +10:00
Nassim Jahnke 725e505514 Also handle release versions on publish 2023-08-11 15:54:59 +10:00
Nassim Jahnke c053975535 Finish publish action 2023-08-11 12:16:42 +10:00
Nassim Jahnke 70725d4aaf Add Hangar publishing 2023-08-11 00:26:51 +10:00
Nassim Jahnke 0d147653f3 Fix spawn tracker mapping data check 2023-08-10 17:13:08 +10:00
Nassim Jahnke f4cc9d4730 Fix double register 2023-08-10 17:06:49 +10:00
Nassim Jahnke 406733b13a 23w32a 2023-08-10 16:55:03 +10:00
Nassim Jahnke 9df7debb7e Finish 23w31a 2023-08-06 13:17:31 +10:00
Nassim Jahnke e12d491b53 Start working on 23w31a 2023-08-05 14:12:45 +10:00
Kichura 4d4e739939 Friendly names in CI, Update Blossom. (#562) 2023-07-25 11:08:22 +10:00
Nassim Jahnke 2904ad54c6 Fix non item display rotation 2023-07-24 20:58:30 +10:00
Nassim Jahnke 92e5fe8a9b Update gradle wrapper 2023-07-11 23:34:47 +02:00
Nassim Jahnke bc0cb7702c Properly handle changed item display rotation 2023-07-03 20:16:52 +02:00
Nassim Jahnke 04d75264e0 Add required 1.18(.1) tag
Fixes #558
2023-06-15 10:10:32 +02:00
tahmid-23 4a308f9d81 Fix 1.19.3->1.19.1 entity sound packet (#555) 2023-06-15 09:56:59 +02:00
EnZaXD 4627142700 Emulate "trim_pattern" registry in 1.19.4 -> 1.20 if not present (#557) 2023-06-14 19:04:28 +02:00
Nassim Jahnke 817080b7a6 Extend correct item rewriter
Fixes #551
2023-06-10 10:14:40 +02:00
Nassim Jahnke 8f51ab2f6a Fix display rotation change 2023-06-09 12:28:08 +02:00
Nassim Jahnke 359cdb13eb Bump version to 4.7.1-SNAPSHOT 2023-06-09 12:19:34 +02:00
Nassim Jahnke 63a3908b53 4.7.0 Release 2023-06-07 11:36:14 +02:00
Nassim Jahnke ceb08c1e55 Update VV usage 2023-06-05 09:10:50 +02:00
Nassim Jahnke c468ec714c Handle servers not sending 1.16 expected tags
Fixes #548
2023-05-28 12:15:42 +02:00
Nassim Jahnke 4fb9fdab9b Add statistics handler to 1.19.4->1.19.3 protocol 2023-05-23 16:43:46 +02:00
Nassim Jahnke d271d3d687 1.20-pre3 2023-05-19 14:34:34 +02:00
Nassim Jahnke 9fa7af7c7b Update nbt file 2023-05-10 16:18:43 +02:00
Nassim Jahnke f591593992 1.20-pre1 2023-05-10 15:54:13 +02:00
Nassim Jahnke e74b5d661d 23w18a, maybe 2023-05-03 15:22:21 +02:00
Nassim Jahnke 483920b729 Sanity checks in item rewriting 2023-05-01 11:33:00 +02:00
Nassim Jahnke 73647ee4fb 23w17a 2023-04-26 19:06:30 +02:00
Nassim Jahnke 97f5ec322a 23w16a 2023-04-20 17:28:25 +02:00
Nassim Jahnke da35067e1d Handle optional block state entity meta 2023-04-18 13:39:59 +02:00
Kichura 65c8024ba7 Add ViaBackwards icon to Fabric (#543) 2023-04-15 14:14:40 +02:00
Nassim Jahnke 377f512f95 23w14a 2023-04-05 15:26:33 +02:00
RK_01 b174dd31b4 Fixed max player count value mapping (#541) 2023-03-31 09:40:18 +02:00
Nassim Jahnke 8eaadd0f18 23w13a 2023-03-29 16:34:17 +02:00
Nassim Jahnke ef1b062449 Handle changed sign nbt 2023-03-24 11:36:32 +01:00
Nassim Jahnke c1383baf14 23w12a 2023-03-22 19:41:00 +01:00
Nassim Jahnke 455e862089 Update mapping files 2023-03-20 10:32:27 +01:00
Nassim Jahnke 0d4257f228 Don't override getTranslatableRewriter in 1.13->1.12, 1.14->1.13 protocols
The method is used in item handling and would otherwise mess up the lore
2023-03-20 10:05:46 +01:00
Pantera (Mad_Daniel) 614207aeef Add remaining sound mappings 2023-03-18 18:24:41 +01:00
Nassim Jahnke 1b268ad4ec Use right type for component metadata 2023-03-18 13:56:53 +01:00
Nassim Jahnke 509055307a Handle 1.12 keybind components
Fixes #474
2023-03-18 13:55:16 +01:00
Nassim Jahnke 68e578a04e Handle translatables in 1.13.1 entity display names 2023-03-18 13:16:22 +01:00
Nassim Jahnke a07550363e Handle shifted 1.19.4 boat types 2023-03-18 12:27:46 +01:00
Nassim Jahnke eb6e9e016a Handle translatables in 1.14/1.15 entity display names 2023-03-18 12:23:14 +01:00
Nassim Jahnke 587a5e487f Improve 1.13->1.12 translatable handling 2023-03-18 10:02:23 +01:00
Nassim Jahnke efded25594 4.6.1 Release 2023-03-16 20:45:16 +01:00
Nassim Jahnke 11e71b1307 Fix #3252 2023-03-15 21:20:33 +01:00
riku6460 974b15243a Fix enchantments in 1.12 -> 1.13 (#533) 2023-03-14 20:01:25 +01:00
Nassim Jahnke e14da27093 Bump version to 4.6.1-SNAPSHOT 2023-03-14 20:01:14 +01:00
Nassim Jahnke 94f8cb662b 4.6.0 Release 2023-03-13 10:51:00 +01:00
Nassim Jahnke 777059d652 Change read type of Teams packet display name 2023-03-13 09:54:09 +01:00
Nassim Jahnke fc565f8cd5 Delay version detection when using legacy injector 2023-03-10 14:29:54 +01:00
Nassim Jahnke 4293289468 Support Folia (leaf's region threaded Minecraft server) 2023-03-10 12:19:22 +01:00
Nassim Jahnke f7acb7ce91 Read custom model data from nbt mapping files, merge dir and packed data 2023-03-09 11:29:59 +01:00
Nassim Jahnke 4a62bb2fbc 1.19.4-pre4 2023-03-08 15:50:03 +01:00
Nassim Jahnke 71361be66c Update mapping files 2023-03-06 10:53:41 +01:00
Nassim Jahnke 3cddb712c8 Fix item loading in 1.13.2->1.13, 1.13->1.12 2023-03-05 21:57:47 +01:00
Nassim Jahnke cba4d03ff0 Small cleanup 2023-03-05 21:45:50 +01:00
Nassim Jahnke 2d1f675834 Mapping fixes 2023-03-05 15:21:06 +01:00
Nassim Jahnke b516103a6e Update to new mappings format 2023-03-04 17:25:45 +01:00
Nassim Jahnke 53daf8328c Fix building 2023-03-02 20:13:33 +01:00
Nassim Jahnke 5d0d6f603b Update VV usage 2023-03-02 13:22:16 +01:00
Nassim Jahnke 565944c317 Handle new container id 2023-03-01 16:09:56 +01:00
Nassim Jahnke 708d6bed52 Update Gradle wrapper 2023-03-01 14:59:26 +01:00
Nassim Jahnke 7349781927 Fix item desync when dropping items on 1.17+ servers as 1.13- clients 2023-02-25 22:42:34 +01:00
Nassim Jahnke 5355316a97 I didn't read the changelogs 🛌 2023-02-22 19:09:19 +01:00
Nassim Jahnke aae59658ec 23w08a 2023-02-22 19:05:08 +01:00
Nassim Jahnke 70c21e995c Update GH actions workflow 2023-02-22 16:27:18 +01:00
Nassim Jahnke fa4cfeb7e9 Things 2023-02-20 17:33:53 +01:00
Nassim Jahnke 1b54d10d91 Small refactor 2023-02-20 13:09:19 +01:00
Nassim Jahnke 3c749bd939 Handle translation additions 2023-02-18 10:32:09 +01:00
Nassim Jahnke 9807eece72 And now there's mappings 2023-02-17 23:42:58 +01:00
Nassim Jahnke 8670d8105d 23w07 without mappings 2023-02-16 13:18:18 +01:00
Nassim Jahnke 27d007aa47 Update Gradle wrapper 2023-02-16 13:10:27 +01:00
Nassim Jahnke 82c01c4b2d Greatly reduce the number of inner classes 2023-02-12 12:17:15 +01:00
Nassim Jahnke 8715c243c9 Improve additional metadata handling
Fixes #527
2023-02-10 12:10:49 +01:00
Nassim Jahnke 27dd148c69 23w06a 2023-02-08 19:31:27 +01:00
Nassim Jahnke 15aa25f0d2 Replace some deprecated api usage 2023-02-04 20:16:43 +01:00
Nassim Jahnke f30fdc1feb Ensure correct packet types in rewriters during compile time 2023-02-04 19:05:29 +01:00
Nassim Jahnke a506b21f56 Don't load mappings in 1.19.4 protocol 2023-02-03 12:13:30 +01:00
Nassim Jahnke 1b4dbc1388 Fix comparator directions in 1.13->1.12
Fixes #524
2023-02-02 12:10:50 +01:00
Nassim Jahnke f1be100b30 Catch and remove bad item nbt from hoverevents in 1.16 conversion
Closes #520
2023-02-02 11:40:12 +01:00
Nassim Jahnke 94210e92f1 Read custom_model_data field from item mappings
Closes #525
2023-02-02 10:51:26 +01:00
Nassim Jahnke 4797914556 23w05a 2023-02-01 16:30:59 +01:00
Lobo Metalúrgico dbf103b788 (fix): 1.12.2 issue because of 1.19 goat horn mapping (#523) 2023-01-20 10:06:40 +01:00
Nassim Jahnke 78bce8895a 23w03a 2023-01-18 18:11:59 +01:00
Nassim Jahnke 4eaf01f008 Update copyright header 2023-01-12 12:41:06 +01:00
Nassim Jahnke 4a9acd6b11 Fix missed 1.19.3 pose change
Fixes #509
2022-12-21 10:44:37 +01:00
Nassim Jahnke 02fcf90b8f Bump version to 4.5.2-SNAPSHOT 2022-12-21 10:28:45 +01:00
Nassim Jahnke 01cdc4416c 4.5.1 Release 2022-12-11 14:40:07 +01:00
Nassim Jahnke 7c2845b884 Fix 1.19.3 player info add 2022-12-11 14:27:41 +01:00
Nassim Jahnke 7cbfffaa68 Fix 1.19.3 sound remapping
Fix #505
2022-12-09 13:24:35 +01:00
Nassim Jahnke 0d0719040c Bump version to 4.5.1-SNAPSHOT 2022-12-09 13:17:55 +01:00
Nassim Jahnke 858fcb2b16 Thank you gradle, very cool 2022-12-09 11:19:11 +01:00
Nassim Jahnke dc4c929108 Add missing empty sound remaps
This is definitely definitely still 4.5.0
2022-12-07 13:53:39 +01:00
Nassim Jahnke 0fe3d9410e 1.19.3-rc3
Definitely still 4.5.0 as well
2022-12-06 12:21:56 +01:00
Nassim Jahnke cc9bf7284a 4.5.0 Release 2022-12-05 21:27:43 +01:00
Nassim Jahnke 383281cb9f 1.19.3-rc1 2022-12-01 17:21:37 +01:00
Nassim Jahnke d18825e700 1.19.3-pre3 2022-11-29 17:33:11 +01:00
Nassim Jahnke 2427690b78 22w46a 2022-11-16 18:30:11 +01:00
Nassim Jahnke a4261d6d9e 22w45a 2022-11-09 16:40:14 +01:00
Nassim Jahnke 091a63e45d 22w44a 2022-11-02 19:20:08 +01:00
Nassim Jahnke 9a9c6c4644 22w43a 2022-10-26 18:28:53 +02:00
Nassim Jahnke 808b1fd2f0 Finish mappings 2022-10-22 12:22:55 +02:00
Nassim Jahnke 9d3ee288df Handle chat types 2022-10-22 11:25:45 +02:00
Nassim Jahnke 100901029e Start working on 22w42a 2022-10-20 22:33:28 +02:00
Kichura 5bf8b59e91 Update actions, Gradle 7.5.1. (#500) 2022-10-15 19:20:35 +02:00
Nassim Jahnke c554027108 Change windswept_forest biome mapping 2022-10-09 15:57:31 +02:00
creeper123123321 4d295fbe2c fix #410 (#499) 2022-10-09 15:56:56 +02:00
Nassim Jahnke 40047330b4 4.4.2 Release 2022-08-21 09:42:48 +02:00
Pieter12345 98304168b8 Fix 1.18.2->1.19 CHAT_MESSAGE using static timestamp (#495) 2022-08-21 09:03:58 +02:00
EDX 3695df1e44 Update PlayerPackets1_11.java (#492) 2022-08-15 11:55:09 +02:00
Nassim Jahnke 958f265e18 Add mangrove/deep dark biome mappings 2022-08-08 13:38:23 +02:00
strider 394c944c50 Add 1.19->1.18 sound mappings (#489) 2022-08-05 16:08:18 +02:00
Nassim JahnkeandTisawesomeness d559c7cff1 Here you go, proper 1.19.1->1.19 and 1.19->1.18.2 support
Co-authored-by: Tisawesomeness <tis_dev@protonmail.com>
2022-08-04 16:59:01 +02:00
Gero 3d4f4438a8 Alter velocity modern forwarding version (#487) 2022-08-03 16:17:55 +02:00
Gero 2972fb8422 Bump version to 4.4.2-SNAPSHOT 2022-08-03 12:47:32 +02:00
Nassim Jahnke 817593ee43 4.4.1 Release 2022-07-28 18:54:02 +02:00
Nassim Jahnke 044980c1a8 Simplify component building 2022-07-28 15:00:16 +02:00
Nassim Jahnke 245bd53850 Add missing 1.19.1 chat types to config 2022-07-28 12:33:36 +02:00
Nassim Jahnke b632e4772f Allow 1.19.0 clients on 1.19.1 servers 2022-07-28 11:47:25 +02:00
Nassim Jahnke b336b8a1fc Tongue 2022-07-27 19:09:40 +02:00
Nassim Jahnke 304b21425c 4.4.0 Release 2022-07-26 18:48:10 +02:00
Nassim Jahnke bb17bb3bfd 1.19.1-rc3 2022-07-26 18:47:14 +02:00
Nassim Jahnke 941bb91be8 1.19.1-pre6 2022-07-20 19:35:04 +02:00
Nassim Jahnke fb334c6c14 1.19.1-pre5 2022-07-15 18:42:57 +02:00
Nassim Jahnke 90460ee99f 1.19.1-pre4 2022-07-08 21:07:57 +02:00
Gero 81a737886a Update chat-types-1.19.1.nbt (#470) 2022-07-06 18:18:28 +02:00
Gero 356158a9d4 team_name -> target (#469) 2022-07-06 18:02:22 +02:00
Nassim Jahnke 32bd9378e1 1.19.1-pre3 2022-07-06 17:55:39 +02:00
Nassim Jahnke 317af16975 Merge remote-tracking branch 'origin/master' into dev
# Conflicts:
#	build.gradle.kts
2022-07-02 19:36:24 +02:00
Nassim Jahnke 3826be4f5f 4.3.1 Release 2022-07-02 19:34:07 +02:00
Gero 282afe94cc Interpret translation keys with %s as the raw translation 2022-07-01 15:20:54 +02:00
Nassim Jahnke 9d86b31cb7 Bump version to 4.4.0-SNAPSHOT, update translation mappings
A break and more funky things
2022-07-01 12:40:43 +02:00
Nassim Jahnke 80041606a7 Merge 1.19.1->1.19 and 1.19->1.18.2 protocols 2022-07-01 12:14:10 +02:00
Gero 41e4172136 Fix chat type style 2022-07-01 10:19:54 +02:00
Gero a856658399 Handle 1.19.1 chat types 2022-07-01 10:17:51 +02:00
Nassim Jahnke 7173bbbbce 1.19.1-pre2 (at least an initial pass) 2022-06-30 19:36:43 +02:00
Nassim Jahnke 54507c6175 Merge remote-tracking branch 'origin/master' into dev 2022-06-28 12:26:27 +02:00
Myles 4dd7d384c8 Add feature request label to issue templates 2022-06-27 13:37:20 +01:00
Nassim Jahnke fc751aedf3 1.19.1-pre1 2022-06-21 22:14:47 +02:00
Nassim Jahnke a1da3dc11c Fix writing books
Fixes #2959
2022-06-17 08:38:23 +02:00
Nassim Jahnke 87c37b08e8 Fix 1.18.0/1 client on 1.19 server
Fixes #454
2022-06-16 20:06:10 +02:00
Gero 187b79f4e1 Fix NPE for chat messages before join game (#456) 2022-06-14 10:39:35 +02:00
Gero b84cda54c3 Fully implement chat types (#455) 2022-06-09 20:49:27 +02:00
Nassim Jahnke f474067eb2 Don't forget to clear 2022-06-09 20:13:36 +02:00
Nassim Jahnke 6a700d228d Properly deal with custom chat type registries 2022-06-09 20:07:58 +02:00
Nassim Jahnke f08223d1e9 Fix trade offers 2022-06-08 10:10:12 +02:00
Nassim Jahnke a5e3a6b563 Bump version to 4.3.1-SNAPSHOT 2022-06-08 10:08:21 +02:00
Nassim Jahnke 65afe42d2c 4.3.0 Release 2022-06-05 11:32:43 +02:00
Nassim Jahnke 9da206e280 Add sanity check in 1.13->1.12 enchantment handler
Closes #2908
2022-06-03 18:19:54 +02:00
Nassim Jahnke c2ae3df1db Fix 1.13->1.12 item cooldown
Fixes #450
2022-05-29 15:51:02 +02:00
Nassim Jahnke dc9fe10779 Fix join game reading 2022-05-23 19:32:54 +02:00
Nassim Jahnke 08a583526e 1.19-pre2 2022-05-23 18:17:17 +02:00
Nassim Jahnke 125fa885f6 Dont clear dimension storage on server switch 2022-05-21 10:57:39 +02:00
Nassim Jahnke 4a1eefcf87 1.19-pre1 2022-05-18 21:08:05 +02:00
Nassim Jahnke 68c0a0b333 Handle argument types, update Via usage 2022-05-14 12:32:10 +02:00
Nassim Jahnke fdc73126f7 Timestamp is millis now, fix dimension storage 2022-05-13 10:11:26 +02:00
Nassim Jahnke 1e0c0ebb2d 22w19a (almost, also more dread) 2022-05-12 23:56:24 +02:00
Nassim Jahnke 5bffa2c51c Fix clientbound chat message reading 2022-05-08 12:05:46 +02:00
Nassim Jahnke 34fa4f85db More or less handle new chat type formats 2022-05-05 11:24:19 +02:00
Nassim Jahnke ef0e412d36 22w18a
I hate codecs
2022-05-04 23:18:50 +02:00
Nassim Jahnke 7df02934f3 22w17a (and even more dread) 2022-04-27 22:38:41 +02:00
Nassim Jahnke d64b259b77 Remove painting variant tags 2022-04-20 21:41:38 +02:00
Nassim Jahnke 8850d5c8ff 22w16b (probably, also ignoring a possible race condition) 2022-04-20 21:00:45 +02:00
Nassim Jahnke 15c7106430 22w15a 2022-04-13 18:48:53 +02:00
Nassim Jahnke 56dfc985d2 Add item mappings, rename carpets tag for older versions 2022-04-06 22:53:45 +02:00
Nassim Jahnke dfa778942c 22w14a 2022-04-06 20:37:16 +02:00
Nassim Jahnke bd71833f18 22w13a 2022-03-31 19:00:43 +02:00
Nassim Jahnke c6f25bf33f Merge remote-tracking branch 'origin/master' into dev 2022-03-30 11:08:33 +02:00
Nassim Jahnke fc22d7e6c8 Don't warn for non-horse armor on horses
Closes #448
2022-03-30 11:07:38 +02:00
Nassim Jahnke 22f604cd7e Fix parrot imitate warden key 2022-03-30 11:06:25 +02:00
Nassim Jahnke a85b9e8100 Remove full frog metadata, add translation mappings 2022-03-24 20:10:19 +01:00
Nassim Jahnke 8d380f4278 22w12a 2022-03-24 19:31:11 +01:00
Nassim Jahnke 1486d58813 Comment out entity effect transformer 2022-03-21 10:42:37 +01:00
Nassim Jahnke 9d3de047a0 Merge remote-tracking branch 'origin/master' into dev
# Conflicts:
#	build.gradle.kts
2022-03-18 12:21:34 +01:00
Nassim Jahnke c75e5bd6a7 4.2.1 Release 2022-03-18 12:07:11 +01:00
Quantum64 30a3a4fb89 Prevent 1.16 -> 1.17 cursor desync with dragging (mostly fixes #389) (#445) 2022-03-18 11:01:46 +01:00
Lucas 9fe9cd3a8a Map smoke directions from 1.13.1 to 1.13 (#413) 2022-03-18 10:52:37 +01:00
Nassim Jahnke 12926980e2 Also remove block entities above 255 in chunk data for 1.17->1.16 2022-03-18 10:32:34 +01:00
Nassim Jahnke 31787b5e5b Fix Velocity/Sponge config location 2022-03-18 10:30:55 +01:00
Nassim Jahnke d56921b611 Actually everything from 22w11a 2022-03-16 23:06:58 +01:00
Nassim Jahnke 15a5e6f710 22w11a 2022-03-16 22:52:19 +01:00
Nassim Jahnke 422f2b699b 1.19 Experimental Snapshot 1 2022-03-16 19:08:08 +01:00
Nassim Jahnke eda8abf55c Handle new biomes for <1.16 clients
Fixes #422
2022-03-13 11:29:34 +01:00
Nassim Jahnke 2b955894d3 Update gradle wrapper to 7.4.1 2022-03-09 18:50:30 +01:00
Nassim Jahnke 539c4e696a Fix long scoreboard objective names for <1.18 clients 2022-03-06 15:41:51 +01:00
Nassim Jahnke aa35ace816 Don't send block entities < 0 for 1.16- players
Fixes ViaVersion/ViaVersion#2833
2022-03-01 10:21:22 +01:00
Nassim Jahnke 8ea7686b2c Bump version to 4.2.1-SNAPSHOT 2022-03-01 10:19:31 +01:00
Nassim Jahnke 7dbd620886 4.2.0 Release 2022-02-24 09:44:23 +01:00
Nassim Jahnke 6a1b0e044a 1.18.2-pre3 2022-02-23 18:13:48 +01:00
Nassim Jahnke afe3584b70 1.18.2 pre1 2022-02-18 18:33:34 +01:00
Nassim Jahnke d8096e7f2e Wither skeletons don't need visible names 2022-02-16 19:15:08 +01:00
Nassim Jahnke 121c735073 Fix registry on respawn 2022-02-09 19:58:04 +01:00
Nassim Jahnke 52698423d0 22w06a 2022-02-09 18:57:28 +01:00
Nassim Jahnke bbff706890 Merge branch 'master' into dev 2022-01-26 09:57:29 +01:00
Nassim Jahnke 2a079be7c2 Make custom world height warning actual warning
Closes ViaVersion/ViaVersion#2805
2022-01-23 17:04:30 +01:00
Nassim Jahnke a8e767250a Fix 1.17->1.16 heightmap conversion
Fixes ViaVersion/ViaVersion#2801
2022-01-22 11:52:09 +01:00
creeper123123321 5593dfb8e5 Fix 1.14->1.13 difficulty (#427) 2022-01-20 12:34:10 +01:00
Nassim Jahnke afd072c313 Mmm 2022-01-19 18:14:21 +01:00
Nassim Jahnke d26cac9622 22w03a 2022-01-19 18:13:33 +01:00
Nassim Jahnke 2c341ab7ad Update copyright 2022-01-09 22:40:10 +01:00
Nassim Jahnke 54eaccca0d Update Sponge module to API v8 2022-01-09 18:58:44 +01:00
Nassim Jahnke 0d5661f8a6 Remove bad 1.13->1.12 sound warning, update shadow
Fixes #424
2022-01-03 18:38:01 +01:00
Nassim Jahnke 7a19cb8d04 Update shadow and Gradle wrapper 2021-12-23 11:41:57 +01:00
FrostBird347 9fddf7b176 Update mapping-1.16.2to1.17.json (#417) 2021-12-05 09:40:42 +01:00
Lucas f687dff702 Add missing block entity NBT on 1.18 (#414) 2021-12-04 16:36:46 +01:00
Nassim Jahnke 249280312e Fix advancement translatables
Closes #415
2021-12-04 16:33:30 +01:00
Nassim Jahnke a200975cda Bump version to 4.1.2-SNAPSHOT 2021-12-04 16:21:06 +01:00
Nassim Jahnke 0163bc8c24 4.1.1 Release 2021-12-03 13:36:40 +01:00
Nassim Jahnke a5a789c440 Fix handling of untracked entities
Some simple meta handlers do not go through entity rewriters, suddenly having to deal with invalid metadata because of plugins' bad concurrency handling
Closes #412
2021-12-03 11:00:52 +01:00
Nassim Jahnke 87aed8f3f2 Fix NPE
Fixes ViaVersion/ViaVersion#2751
2021-12-03 08:59:28 +01:00
Nassim Jahnke cadab9e6bb Throw error on unhandled 1.14->1.13 metadata 2021-12-02 12:43:42 +01:00
Nassim Jahnke 13b5545999 Fix vibration and transition particle meta 2021-12-02 11:11:34 +01:00
Nassim Jahnke f4a6c20695 Update Gradle wrapper to 7.3.1 2021-12-02 11:02:55 +01:00
Nassim Jahnke ff583e40fb Fix 1.18 mountain biomes in biome registry 2021-12-01 17:04:05 +01:00
Nassim Jahnke c8b0ca48de Bump version to 4.1.1-SNAPSHOT 2021-12-01 17:03:41 +01:00
358 changed files with 26551 additions and 29702 deletions

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
[*]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = false
tab_width = 4
[*.java]
ij_java_class_count_to_use_import_on_demand = 999999
ij_java_names_count_to_use_import_on_demand = 999999
ij_java_imports_layout = *, |, $*
ij_java_generate_final_locals = true
ij_java_generate_final_parameters = true
[{*.json,*.yml}]
indent_size = 2
+2
View File
@@ -0,0 +1,2 @@
github: kennytv
patreon: kennytv
+5 -5
View File
@@ -21,11 +21,11 @@ body:
attributes:
label: Console Error
description: |
If you encounter warnings/errors in your console, **paste them with https://paste.gg/ and put the paste link here**.
If you encounter warnings/errors in your console, **paste them with https://mclo.gs/ and put the paste link here**.
If the error is small/less than 10 lines, you may put it directly into this field.
value: |
```
Put the paste.gg link or text here.
Put the mclo.gs link or text here.
```
placeholder: Please do not remove the grave accents; simply replace the line of text in the middle.
validations:
@@ -69,9 +69,9 @@ body:
attributes:
label: Additional Server Info
description: |
Do you use a proxy (eg. BungeeCord)? What software do you use and what plugins?
Do you use a proxy (eg. Velocity)? What software do you use and what plugins?
placeholder: |
Example: "I also use BungeeCord with the following plugins: x, y, z"
Example: "I also use Velocity with the following plugins: x, y, z"
validations:
required: false
@@ -80,7 +80,7 @@ body:
label: Checklist
description: Make sure you have followed each of the steps outlined here.
options:
- label: Via plugins are only running on **EITHER** the backend servers (e.g. Paper) **OR** the proxy (e.g. BungeeCord), **not on both**.
- label: Via plugins are only running on **EITHER** the backend servers (e.g. Paper) **OR** the proxy (e.g. Velocity), **not on both**.
required: true
- label: I have included a ViaVersion dump.
required: true
+2 -1
View File
@@ -1,5 +1,6 @@
name: Feature Request
description: Suggest a feature to be added
labels: [Feature Request]
body:
- type: textarea
@@ -34,4 +35,4 @@ body:
description: |
Does the feature apply to any specific version or environment?
validations:
required: false
required: false
+11 -13
View File
@@ -1,25 +1,23 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Java CI with Gradle
on: [push, pull_request]
jobs:
build:
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'adopt'
java-version: 11
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Build with Gradle
run: ./gradlew build
- uses: actions/upload-artifact@v2
with:
name: artifact
path: build/libs
+27
View File
@@ -0,0 +1,27 @@
name: Publish to Hangar and Modrinth
on:
push:
branches:
- master
- dev
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Publish
env:
HANGAR_TOKEN: ${{ secrets.HANGAR_TOKEN }}
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
run: ./gradlew build modrinth publishAllPublicationsToHangar --stacktrace
+2
View File
@@ -18,6 +18,8 @@ hs_err_pid*
# Ignore IDEA directory
.idea/*
!.idea/copyright/*
!.idea/scopes/*
# Include the project's dictionary
!.idea/dictionaries/
+10
View File
@@ -0,0 +1,10 @@
<component name="CopyrightManager">
<settings>
<module2copyright>
<element module="ViaBackwards" copyright="viabackwards-gpl" />
</module2copyright>
<LanguageOptions name="__TEMPLATE__">
<option name="addBlankAfter" value="false" />
</LanguageOptions>
</settings>
</component>
+6
View File
@@ -0,0 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards&#10;Copyright (C) 2016-&amp;#36;today.year ViaVersion and contributors&#10;&#10;This program is free software: you can redistribute it and/or modify&#10;it under the terms of the GNU General Public License as published by&#10;the Free Software Foundation, either version 3 of the License, or&#10;(at your option) any later version.&#10;&#10;This program is distributed in the hope that it will be useful,&#10;but WITHOUT ANY WARRANTY; without even the implied warranty of&#10;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the&#10;GNU General Public License for more details.&#10;&#10;You should have received a copy of the GNU General Public License&#10;along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;." />
<option name="myName" value="viabackwards-gpl" />
</copyright>
</component>
+3
View File
@@ -0,0 +1,3 @@
<component name="DependencyValidationManager">
<scope name="ViaBackwards" pattern="com.viaversion.viabackwards..*" />
</component>
+28 -16
View File
@@ -4,43 +4,55 @@
[![Build Status](https://github.com/ViaVersion/ViaBackwards/actions/workflows/gradle.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaBackwards/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**Allows older Minecraft client versions to connect to newer server versions**
**Allows older Minecraft client versions to connect to newer server versions.**
Requires [ViaVersion](https://hangar.papermc.io/ViaVersion/ViaVersion) to be installed..
Supported Versions
-
**Green** = ViaVersion\
**Purple** = ViaBackwards addition
As a plugin, ViaBackwards runs on servers on releases 1.10-latest. Versions from the dev branch will also support the
latest snapshot. You can also use ViaBackwards in ViaFabric or ViaFabricPlus.
![supported_versions](https://i.imgur.com/O2KAFFL.png)
See [HERE](https://github.com/ViaVersion) for an overview of the different Via* projects.
Releases / Dev Builds
Releases/Dev Builds
-
**Requires [ViaVersion](https://www.spigotmc.org/resources/viaversion.19254/) to be installed**
You can find the latest dev builds here:\
**Jenkins:** https://ci.viaversion.com/view/ViaBackwards/
You can find releases in the following places:
**Spigot page:** https://www.spigotmc.org/resources/viabackwards.27448/
- **Hangar (for our plugins)**: https://hangar.papermc.io/ViaVersion/ViaBackwards
- **Modrinth (for our mods)**: https://modrinth.com/mod/viabackwards
- **GitHub**: https://github.com/ViaVersion/ViaBackwards/releases
**CurseForge page:** https://www.curseforge.com/minecraft/mc-mods/viabackwards
Dev builds for **all** of our projects are on our Jenkins server:
- **Jenkins**: https://ci.viaversion.com/view/ViaBackwards/
Known issues
-
* Custom 1.17+ min_y and height world values are not and will (most likely) never be supported => Clients older than 1.17 will not be able to see or interact with blocks below y=0 and above y=255
* < 1.17 clients on 1.17+ servers might experience inventory desyncs on certain inventory click actions
* 1.17+ min_y and height world values that are not 0/256 **are not supported**. Clients older than
1.17 will not be able to see or interact with blocks below y=0 and above y=255
* <1.17 clients on 1.17+ servers might experience inventory desyncs on certain inventory click actions
* Sound mappings are incomplete ([see here](https://github.com/ViaVersion/ViaBackwards/issues/326))
* <1.19.4 clients on 1.20+ servers won't be able to use the smithing table, this can be fixed by
installing [AxSmithing](https://github.com/ViaVersionAddons/AxSmithing)
Other Links
-
**Maven:** https://repo.viaversion.com
**Issue tracker:** https://github.com/ViaVersion/ViaBackwards/issues
**List of contributors:** https://github.com/ViaVersion/ViaBackwards/graphs/contributors
Building
-
After cloning this repository, build the project with Gradle by running `./gradlew build` and take the created jar out
of the `build/libs` directory.
You need JDK 17 or newer to build ViaBackwards.
License
-
This project is licensed under the [GNU General Public License](LICENSE).
This project is licensed under the [GNU General Public License Version 3](LICENSE).
Special Thanks
-
+1 -1
View File
@@ -8,5 +8,5 @@ repositories {
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("gradle.plugin.com.github.johnrengelman", "shadow", "7.1.0")
implementation("com.github.johnrengelman", "shadow", "8.1.1")
}
+27 -26
View File
@@ -1,34 +1,8 @@
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.named
import java.io.ByteArrayOutputStream
fun Project.publishShadowJar() {
configurePublication {
artifact(tasks["shadowJar"])
artifact(tasks["sourcesJar"])
}
}
fun Project.publishJavaComponents() {
configurePublication {
from(components["java"])
}
}
private fun Project.configurePublication(configurer: MavenPublication.() -> Unit) {
extensions.configure<PublishingExtension> {
publications.named<MavenPublication>("mavenJava") {
apply(configurer)
}
}
}
fun Project.latestCommitHash(): String {
val byteOut = ByteArrayOutputStream()
exec {
@@ -38,6 +12,33 @@ fun Project.latestCommitHash(): String {
return byteOut.toString(Charsets.UTF_8.name()).trim()
}
fun Project.latestCommitMessage(): String {
val byteOut = ByteArrayOutputStream()
exec {
commandLine = listOf("git", "log", "-1", "--pretty=%B")
standardOutput = byteOut
}
return byteOut.toString(Charsets.UTF_8.name()).trim()
}
fun Project.branchName(): String {
val byteOut = ByteArrayOutputStream()
exec {
commandLine = listOf("git", "rev-parse", "--abbrev-ref", "HEAD")
standardOutput = byteOut
}
return byteOut.toString(Charsets.UTF_8.name()).trim()
}
fun Project.parseMinecraftSnapshotVersion(version: String): String? {
val separatorIndex = version.indexOf('-')
val lastSeparatorIndex = version.lastIndexOf('-')
if (separatorIndex == -1 || separatorIndex == lastSeparatorIndex) {
return null
}
return version.substring(separatorIndex + 1, lastSeparatorIndex)
}
fun JavaPluginExtension.javaTarget(version: Int) {
sourceCompatibility = JavaVersion.toVersion(version)
targetCompatibility = JavaVersion.toVersion(version)
@@ -1,13 +1,12 @@
plugins {
`java-library`
`maven-publish`
}
tasks {
// Variable replacements
processResources {
filesMatching(listOf("plugin.yml", "mcmod.info", "fabric.mod.json", "bungee.yml")) {
expand("version" to project.version, "description" to project.description, "url" to "https://github.com/ViaVersion/ViaBackwards")
filesMatching(listOf("plugin.yml", "fabric.mod.json")) {
expand("version" to project.version, "description" to project.description, "url" to "https://viaversion.com/backwards")
}
}
javadoc {
@@ -21,22 +20,6 @@ tasks {
}
java {
javaTarget(8)
javaTarget(17)
withSourcesJar()
}
publishing {
publications.create<MavenPublication>("mavenJava") {
groupId = rootProject.group as String
artifactId = project.name
version = rootProject.version as String
}
repositories.maven {
name = "Via"
url = uri("https://repo.viaversion.com/")
credentials(PasswordCredentials::class)
authentication {
create<BasicAuthentication>("basic")
}
}
}
}
@@ -1,10 +0,0 @@
plugins {
id("vb.shadow-conventions")
}
tasks {
shadowJar {
archiveFileName.set("ViaBackwards-${project.name.substringAfter("viabackwards-").capitalize()}-${project.version}.jar")
destinationDirectory.set(rootProject.layout.buildDirectory.dir("libs"))
}
}
@@ -4,6 +4,7 @@ import org.gradle.kotlin.dsl.named
plugins {
id("vb.base-conventions")
id("maven-publish")
id("com.github.johnrengelman.shadow")
}
@@ -21,7 +22,24 @@ tasks {
}
}
publishShadowJar()
publishing {
publications.create<MavenPublication>("mavenJava") {
groupId = rootProject.group as String
artifactId = project.name
version = rootProject.version as String
artifact(tasks["shadowJar"])
artifact(tasks["sourcesJar"])
}
repositories.maven {
name = "Via"
url = uri("https://repo.viaversion.com/")
credentials(PasswordCredentials::class)
authentication {
create<BasicAuthentication>("basic")
}
}
}
fun ShadowJar.configureRelocations() {
relocate("com.google.gson", "com.viaversion.viaversion.libs.gson")
@@ -1,5 +0,0 @@
plugins {
id("vb.base-conventions")
}
publishJavaComponents()
+10 -16
View File
@@ -5,27 +5,21 @@ plugins {
allprojects {
group = "com.viaversion"
version = "4.1.0"
description = "Allow older clients to join newer server versions."
version = property("projectVersion") as String // from gradle.properties
description = "Allows older Minecraft client versions to connect to newer server versions."
}
val platforms = setOf(
projects.viabackwardsBukkit,
projects.viabackwardsBungee,
projects.viabackwardsFabric,
projects.viabackwardsSponge,
projects.viabackwardsVelocity
).map { it.dependencyProject }
// Would otherwise contain api/depdency modules if at some point needed
val special = setOf(
projects.viabackwards
val main = setOf(
projects.viabackwards,
projects.viabackwardsCommon,
projects.viabackwardsBukkit,
projects.viabackwardsVelocity,
projects.viabackwardsFabric
).map { it.dependencyProject }
subprojects {
when (this) {
in platforms -> plugins.apply("vb.platform-conventions")
in special -> plugins.apply("vb.base-conventions")
else -> plugins.apply("vb.standard-conventions")
in main -> plugins.apply("vb.shadow-conventions")
else -> plugins.apply("vb.base-conventions")
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
dependencies {
implementation(projects.viabackwardsCommon)
compileOnlyApi(projects.viabackwardsCommon)
compileOnly(libs.paper) {
exclude("com.google.code.gson", "gson")
exclude("javax.persistence", "persistence-api")
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,47 +19,56 @@
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.viaversion.ViaVersionPlugin;
import com.viaversion.viabackwards.listener.PlayerItemDropListener;
import com.viaversion.viabackwards.protocol.v1_20_2to1_20.provider.AdvancementCriteriaProvider;
import com.viaversion.viabackwards.provider.BukkitAdvancementCriteriaProvider;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bukkit.platform.BukkitViaLoader;
import java.io.File;
import org.bukkit.plugin.java.JavaPlugin;
public class BukkitPlugin extends JavaPlugin implements ViaBackwardsPlatform {
@Override
public void onLoad() {
if (!ViaVersionPlugin.getInstance().isLateBind()) {
init();
}
public BukkitPlugin() {
Via.getManager().addEnableListener(() -> init(new File(getDataFolder(), "config.yml")));
}
@Override
public void onEnable() {
if (ViaVersionPlugin.getInstance().isLateBind()) {
init();
if (Via.getManager().getInjector().lateProtocolVersionSetting()) {
// Enable in the next tick
Via.getPlatform().runSync(this::enable, 1);
} else {
enable();
}
}
private void init() {
init(getDataFolder());
Via.getPlatform().runSync(this::onServerLoaded);
}
private void enable() {
final ProtocolVersion protocolVersion = Via.getAPI().getServerVersion().highestSupportedProtocolVersion();
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_17)) {
new PlayerItemDropListener(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_16)) {
new FireExtinguishListener(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_14)) {
new LecternInteractListener(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_12)) {
new FireDamageListener(this).register();
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_11)) {
new BlockBreakListener(this).register();
}
private void onServerLoaded() {
BukkitViaLoader loader = (BukkitViaLoader) Via.getManager().getLoader();
int protocolVersion = Via.getAPI().getServerVersion().highestSupportedVersion();
if (protocolVersion >= ProtocolVersion.v1_16.getVersion()) {
loader.storeListener(new FireExtinguishListener(this)).register();
}
if (protocolVersion >= ProtocolVersion.v1_14.getVersion()) {
loader.storeListener(new LecternInteractListener(this)).register();
}
if (protocolVersion >= ProtocolVersion.v1_12.getVersion()) {
loader.storeListener(new FireDamageListener(this)).register();
final ViaProviders providers = Via.getManager().getProviders();
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_2)) {
providers.use(AdvancementCriteriaProvider.class, new BukkitAdvancementCriteriaProvider());
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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_11to1_10.Protocol1_11To1_10;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import org.bukkit.GameMode;
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 BlockBreakListener extends ViaBukkitListener {
public BlockBreakListener(final BukkitPlugin plugin) {
super(plugin, Protocol1_11To1_10.class);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onBlockBreak(final BlockBreakEvent event) {
if (!event.isCancelled()) {
return;
}
final Player player = event.getPlayer();
if (player.getGameMode() == GameMode.CREATIVE || !isOnPipe(player)) {
return;
}
// Resend the item in the hand to sync durability
final int slot = player.getInventory().getHeldItemSlot();
final ItemStack item = player.getInventory().getItem(slot);
if (item != null && item.getType().getMaxDurability() > 0) {
player.getInventory().setItem(slot, item);
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,7 @@
package com.viaversion.viabackwards.listener;
import com.viaversion.viabackwards.BukkitPlugin;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.Protocol1_11_1To1_12;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.Protocol1_12To1_11_1;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
@@ -31,7 +31,7 @@ import org.bukkit.event.entity.EntityDamageEvent;
public class FireDamageListener extends ViaBukkitListener {
public FireDamageListener(BukkitPlugin plugin) {
super(plugin, Protocol1_11_1To1_12.class);
super(plugin, Protocol1_12To1_11_1.class);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@@ -40,9 +40,9 @@ public class FireDamageListener extends ViaBukkitListener {
EntityDamageEvent.DamageCause cause = event.getCause();
if (cause != EntityDamageEvent.DamageCause.FIRE
&& cause != EntityDamageEvent.DamageCause.FIRE_TICK
&& cause != EntityDamageEvent.DamageCause.LAVA
&& cause != EntityDamageEvent.DamageCause.DROWNING) {
&& cause != EntityDamageEvent.DamageCause.FIRE_TICK
&& cause != EntityDamageEvent.DamageCause.LAVA
&& cause != EntityDamageEvent.DamageCause.DROWNING) {
return;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,7 @@
package com.viaversion.viabackwards.listener;
import com.viaversion.viabackwards.BukkitPlugin;
import com.viaversion.viabackwards.protocol.protocol1_15_2to1_16.Protocol1_15_2To1_16;
import com.viaversion.viabackwards.protocol.v1_16to1_15_2.Protocol1_16To1_15_2;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -31,7 +31,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
public class FireExtinguishListener extends ViaBukkitListener {
public FireExtinguishListener(BukkitPlugin plugin) {
super(plugin, Protocol1_15_2To1_16.class);
super(plugin, Protocol1_16To1_15_2.class);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,7 @@
package com.viaversion.viabackwards.listener;
import com.viaversion.viabackwards.BukkitPlugin;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viabackwards.protocol.v1_14to1_13_2.Protocol1_14To1_13_2;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import org.bukkit.Material;
import org.bukkit.block.Block;
@@ -33,7 +33,7 @@ import org.bukkit.inventory.meta.BookMeta;
public class LecternInteractListener extends ViaBukkitListener {
public LecternInteractListener(BukkitPlugin plugin) {
super(plugin, Protocol1_13_2To1_14.class);
super(plugin, Protocol1_14To1_13_2.class);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@@ -53,6 +53,7 @@ public class LecternInteractListener extends ViaBukkitListener {
// Open a book with the text of the lectern's writable book
ItemStack newBook = new ItemStack(Material.WRITTEN_BOOK);
BookMeta newBookMeta = (BookMeta) newBook.getItemMeta();
//noinspection deprecation
newBookMeta.setPages(meta.getPages());
newBookMeta.setAuthor("an upsidedown person");
newBookMeta.setTitle("buk");
@@ -0,0 +1,48 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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_13_1to1_13.Protocol1_13_1To1_13;
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.player.PlayerDropItemEvent;
import org.bukkit.inventory.ItemStack;
public class PlayerItemDropListener extends ViaBukkitListener {
public PlayerItemDropListener(final BukkitPlugin plugin) {
super(plugin, Protocol1_13_1To1_13.class); // Starts with 1.13 clients on 1.17 servers
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onItemDrop(final PlayerDropItemEvent event) {
final Player player = event.getPlayer();
if (!isOnPipe(player)) {
return;
}
// Resend the item in the hand
final int slot = player.getInventory().getHeldItemSlot();
final ItemStack item = player.getInventory().getItem(slot);
player.getInventory().setItem(slot, item);
}
}
@@ -0,0 +1,34 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.provider;
import com.viaversion.viabackwards.protocol.v1_20_2to1_20.provider.AdvancementCriteriaProvider;
import org.bukkit.Bukkit;
import org.bukkit.NamespacedKey;
import org.bukkit.advancement.Advancement;
public final class BukkitAdvancementCriteriaProvider extends AdvancementCriteriaProvider {
private static final String[] EMPTY_CRITERIA = new String[0];
@Override
public String[] getCriteria(final String key) {
final Advancement advancement = Bukkit.getAdvancement(NamespacedKey.fromString(key));
return advancement == null ? EMPTY_CRITERIA : advancement.getCriteria().toArray(EMPTY_CRITERIA);
}
}
+3 -2
View File
@@ -1,10 +1,11 @@
name: ViaBackwards
version: ${version}
description: Allow older Minecraft versions to connect to a newer server version.
description: ${description}
main: com.viaversion.viabackwards.BukkitPlugin
api-version: 1.13
folia-supported: true
authors: [Matsv, kennytv, Gerrygames, creeper123123321, ForceUpdate1]
authors: [Matsv, kennytv, Gerrygames, creeper123123321, ForceUpdate1, EnZaXD]
website: ${url}
depend: [ViaVersion]
-4
View File
@@ -1,4 +0,0 @@
dependencies {
implementation(projects.viabackwardsCommon)
compileOnly(libs.bungee)
}
-5
View File
@@ -1,5 +0,0 @@
name: ViaBackwards
main: com.viaversion.viabackwards.BungeePlugin
author: "Matsv, kennytv, Gerrygames, creeper123123321, ForceUpdate1"
version: ${version}
depends: [ViaVersion]
+10 -3
View File
@@ -1,10 +1,17 @@
plugins {
id("net.kyori.blossom")
id("org.jetbrains.gradle.plugin.idea-ext")
}
blossom {
replaceToken("\$VERSION", project.version)
replaceToken("\$IMPL_VERSION", "git-ViaBackwards-${project.version}:${rootProject.latestCommitHash()}")
sourceSets {
main {
blossom {
javaSources {
property("version", project.version.toString())
property("impl_version", "git-ViaBackwards-${project.version}:${rootProject.latestCommitHash()}")
}
}
}
}
dependencies {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2023 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
@@ -15,20 +15,18 @@
* 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.utils;
package com.viaversion.viabackwards.api.exceptions;
public final class VersionInfo {
import java.io.IOException;
public static final String VERSION = "{{ version }}";
private static final String IMPLEMENTATION_VERSION = "{{ impl_version }}";
public class RemovedValueException extends IOException {
public static String getVersion() {
return VERSION;
}
/**
* May be cached since it is never actually printed, only checked.
*/
public static final RemovedValueException EX = new RemovedValueException() {
@Override
public Throwable fillInStackTrace() {
return this;
}
};
public static String getImplementationVersion() {
return IMPLEMENTATION_VERSION;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,13 +22,13 @@ import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.api.ViaBackwardsConfig;
import com.viaversion.viabackwards.api.ViaBackwardsPlatform;
public class ViaBackwards {
public final class ViaBackwards {
private static ViaBackwardsPlatform platform;
private static ViaBackwardsConfig config;
public static void init(ViaBackwardsPlatform platform, ViaBackwardsConfig config) {
Preconditions.checkArgument(platform != null, "ViaBackwards is already initialized");
Preconditions.checkArgument(ViaBackwards.platform == null, "ViaBackwards is already initialized");
ViaBackwards.platform = platform;
ViaBackwards.config = config;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,13 @@
package com.viaversion.viabackwards;
import com.viaversion.viaversion.util.Config;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class ViaBackwardsConfig extends Config implements com.viaversion.viabackwards.api.ViaBackwardsConfig {
@@ -33,14 +34,15 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
private boolean alwaysShowOriginalMobName;
private boolean fix1_13FormattedInventoryTitles;
private boolean handlePingsAsInvAcknowledgements;
private boolean suppressEmulationWarnings;
public ViaBackwardsConfig(File configFile) {
super(configFile);
public ViaBackwardsConfig(File configFile, Logger logger) {
super(configFile, logger);
}
@Override
public void reloadConfig() {
super.reloadConfig();
public void reload() {
super.reload();
loadFields();
}
@@ -51,6 +53,7 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
fix1_13FormattedInventoryTitles = getBoolean("fix-formatted-inventory-titles", true);
alwaysShowOriginalMobName = getBoolean("always-show-original-mob-name", true);
handlePingsAsInvAcknowledgements = getBoolean("handle-pings-as-inv-acknowledgements", false);
suppressEmulationWarnings = getBoolean("suppress-emulation-warnings", false);
}
@Override
@@ -83,11 +86,21 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
return handlePingsAsInvAcknowledgements || Boolean.getBoolean("com.viaversion.handlePingsAsInvAcknowledgements");
}
@Override
public boolean suppressEmulationWarnings() {
return suppressEmulationWarnings;
}
@Override
public URL getDefaultConfigURL() {
return getClass().getClassLoader().getResource("assets/viabackwards/config.yml");
}
@Override
public InputStream getDefaultConfigInputStream() {
return getClass().getClassLoader().getResourceAsStream("assets/viabackwards/config.yml");
}
@Override
protected void handleConfig(Map<String, Object> map) {
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,7 @@
*/
package com.viaversion.viabackwards.api;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
@@ -26,14 +26,14 @@ import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class BackwardsProtocol<C1 extends ClientboundPacketType, C2 extends ClientboundPacketType, S1 extends ServerboundPacketType, S2 extends ServerboundPacketType>
extends AbstractProtocol<C1, C2, S1, S2> {
public abstract class BackwardsProtocol<CU extends ClientboundPacketType, CM extends ClientboundPacketType, SM extends ServerboundPacketType, SU extends ServerboundPacketType>
extends AbstractProtocol<CU, CM, SM, SU> {
protected BackwardsProtocol() {
}
protected BackwardsProtocol(@Nullable Class<C1> oldClientboundPacketEnum, @Nullable Class<C2> clientboundPacketEnum,
@Nullable Class<S1> oldServerboundPacketEnum, @Nullable Class<S2> serverboundPacketEnum) {
protected BackwardsProtocol(@Nullable Class<CU> oldClientboundPacketEnum, @Nullable Class<CM> clientboundPacketEnum,
@Nullable Class<SM> oldServerboundPacketEnum, @Nullable Class<SU> serverboundPacketEnum) {
super(oldClientboundPacketEnum, clientboundPacketEnum, oldServerboundPacketEnum, serverboundPacketEnum);
}
@@ -44,6 +44,16 @@ public abstract class BackwardsProtocol<C1 extends ClientboundPacketType, C2 ext
Via.getManager().getProtocolManager().addMappingLoaderFuture(getClass(), protocolClass, runnable);
}
@Override
protected void registerPackets() {
super.registerPackets();
final BackwardsMappingData mappingData = getMappingData();
if (mappingData != null && mappingData.getViaVersionProtocolClass() != null) {
executeAsyncAfterLoaded(mappingData.getViaVersionProtocolClass(), this::loadMappingData);
}
}
@Override
public boolean hasMappingDataToLoad() {
// Manually load them later, since they depend on VV's mappings
@@ -51,11 +61,12 @@ public abstract class BackwardsProtocol<C1 extends ClientboundPacketType, C2 ext
}
@Override
public @Nullable BackwardsMappings getMappingData() { // Change return type to BackwardsMappings
public @Nullable BackwardsMappingData getMappingData() { // Change return type to BackwardsMappings
return null;
}
public @Nullable TranslatableRewriter getTranslatableRewriter() {
@Override
public @Nullable TranslatableRewriter<CU> getComponentRewriter() {
return null;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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;
public interface ViaBackwardsConfig {
import com.viaversion.viaversion.api.configuration.Config;
public interface ViaBackwardsConfig extends Config {
/**
* Mimics name and level of a custom enchant through the item's lore.
@@ -40,6 +42,11 @@ public interface ViaBackwardsConfig {
*/
boolean isFix1_13FacePlayer();
/**
* Converts the 1.13 face look-at packet for 1.12- players. Requires a bit of extra caching.
*
* @return true if enabled
*/
boolean fix1_13FormattedInventoryTitle();
/**
@@ -49,5 +56,18 @@ public interface ViaBackwardsConfig {
*/
boolean alwaysShowOriginalMobName();
/**
* Sends inventory acknowledgement packets to act as a replacement for ping packets for sub 1.17 clients.
* This only takes effect for ids in the short range. Useful for anticheat compatibility.
*
* @return true if enabled
*/
boolean handlePingsAsInvAcknowledgements();
/**
* 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();
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,93 +21,126 @@ package com.viaversion.viabackwards.api;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.ViaBackwardsConfig;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.Protocol1_11_1To1_12;
import com.viaversion.viabackwards.protocol.protocol1_11to1_11_1.Protocol1_11To1_11_1;
import com.viaversion.viabackwards.protocol.protocol1_12_1to1_12_2.Protocol1_12_1To1_12_2;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viabackwards.protocol.protocol1_12to1_12_1.Protocol1_12To1_12_1;
import com.viaversion.viabackwards.protocol.protocol1_13_1to1_13_2.Protocol1_13_1To1_13_2;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viabackwards.protocol.protocol1_13to1_13_1.Protocol1_13To1_13_1;
import com.viaversion.viabackwards.protocol.protocol1_14_1to1_14_2.Protocol1_14_1To1_14_2;
import com.viaversion.viabackwards.protocol.protocol1_14_2to1_14_3.Protocol1_14_2To1_14_3;
import com.viaversion.viabackwards.protocol.protocol1_14_3to1_14_4.Protocol1_14_3To1_14_4;
import com.viaversion.viabackwards.protocol.protocol1_14_4to1_15.Protocol1_14_4To1_15;
import com.viaversion.viabackwards.protocol.protocol1_14to1_14_1.Protocol1_14To1_14_1;
import com.viaversion.viabackwards.protocol.protocol1_15_1to1_15_2.Protocol1_15_1To1_15_2;
import com.viaversion.viabackwards.protocol.protocol1_15_2to1_16.Protocol1_15_2To1_16;
import com.viaversion.viabackwards.protocol.protocol1_15to1_15_1.Protocol1_15To1_15_1;
import com.viaversion.viabackwards.protocol.protocol1_16_1to1_16_2.Protocol1_16_1To1_16_2;
import com.viaversion.viabackwards.protocol.protocol1_16_2to1_16_3.Protocol1_16_2To1_16_3;
import com.viaversion.viabackwards.protocol.protocol1_16_3to1_16_4.Protocol1_16_3To1_16_4;
import com.viaversion.viabackwards.protocol.protocol1_16_4to1_17.Protocol1_16_4To1_17;
import com.viaversion.viabackwards.protocol.protocol1_16to1_16_1.Protocol1_16To1_16_1;
import com.viaversion.viabackwards.protocol.protocol1_17_1to1_18.Protocol1_17_1To1_18;
import com.viaversion.viabackwards.protocol.protocol1_17to1_17_1.Protocol1_17To1_17_1;
import com.viaversion.viabackwards.protocol.protocol1_9_4to1_10.Protocol1_9_4To1_10;
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.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_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_13_1to1_13.Protocol1_13_1To1_13;
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_15_1to1_15.Protocol1_15_1To1_15;
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_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_18_2to1_18.Protocol1_18_2To1_18;
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_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_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_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.utils.VersionInfo;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.update.Version;
import java.io.File;
import java.util.Arrays;
import java.util.logging.Logger;
public interface ViaBackwardsPlatform {
String MINIMUM_VV_VERSION = "4.1.0";
String IMPL_VERSION = "$IMPL_VERSION";
String MINIMUM_VV_VERSION = "5.0.0";
/**
* Initialize ViaBackwards.
*/
default void init(File dataFolder) {
ViaBackwardsConfig config = new ViaBackwardsConfig(new File(dataFolder, "config.yml"));
config.reloadConfig();
default void init(final File configFile) {
ViaBackwardsConfig config = new ViaBackwardsConfig(configFile, getLogger());
config.reload();
Via.getManager().getConfigurationProvider().register(config);
ViaBackwards.init(this, config);
if (isOutdated()) return;
if (isOutdated()) {
disable();
return;
}
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
Via.getManager().getSubPlatforms().add(VersionInfo.getImplementationVersion());
getLogger().info("Loading translations...");
TranslatableRewriter.loadTranslatables();
ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_9_4To1_10(), ProtocolVersion.v1_9_3, ProtocolVersion.v1_10);
getLogger().info("Registering protocols...");
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);
protocolManager.registerProtocol(new Protocol1_10To1_9_3(), ProtocolVersion.v1_9_3, ProtocolVersion.v1_10);
protocolManager.registerProtocol(new Protocol1_10To1_11(), ProtocolVersion.v1_10, ProtocolVersion.v1_11);
protocolManager.registerProtocol(new Protocol1_11To1_11_1(), ProtocolVersion.v1_11, ProtocolVersion.v1_11_1);
protocolManager.registerProtocol(new Protocol1_11To1_10(), ProtocolVersion.v1_10, ProtocolVersion.v1_11);
protocolManager.registerProtocol(new Protocol1_11_1To1_11(), ProtocolVersion.v1_11, ProtocolVersion.v1_11_1);
protocolManager.registerProtocol(new Protocol1_11_1To1_12(), ProtocolVersion.v1_11_1, ProtocolVersion.v1_12);
protocolManager.registerProtocol(new Protocol1_12To1_12_1(), ProtocolVersion.v1_12, ProtocolVersion.v1_12_1);
protocolManager.registerProtocol(new Protocol1_12_1To1_12_2(), ProtocolVersion.v1_12_1, ProtocolVersion.v1_12_2);
protocolManager.registerProtocol(new Protocol1_12To1_11_1(), ProtocolVersion.v1_11_1, ProtocolVersion.v1_12);
protocolManager.registerProtocol(new Protocol1_12_1To1_12(), ProtocolVersion.v1_12, ProtocolVersion.v1_12_1);
protocolManager.registerProtocol(new Protocol1_12_2To1_12_1(), ProtocolVersion.v1_12_1, ProtocolVersion.v1_12_2);
protocolManager.registerProtocol(new Protocol1_12_2To1_13(), ProtocolVersion.v1_12_2, ProtocolVersion.v1_13);
protocolManager.registerProtocol(new Protocol1_13To1_13_1(), ProtocolVersion.v1_13, ProtocolVersion.v1_13_1);
protocolManager.registerProtocol(new Protocol1_13_1To1_13_2(), ProtocolVersion.v1_13_1, ProtocolVersion.v1_13_2);
protocolManager.registerProtocol(new Protocol1_13To1_12_2(), ProtocolVersion.v1_12_2, ProtocolVersion.v1_13);
protocolManager.registerProtocol(new Protocol1_13_1To1_13(), ProtocolVersion.v1_13, ProtocolVersion.v1_13_1);
protocolManager.registerProtocol(new Protocol1_13_2To1_13_1(), ProtocolVersion.v1_13_1, ProtocolVersion.v1_13_2);
protocolManager.registerProtocol(new Protocol1_13_2To1_14(), ProtocolVersion.v1_13_2, ProtocolVersion.v1_14);
protocolManager.registerProtocol(new Protocol1_14To1_14_1(), ProtocolVersion.v1_14, ProtocolVersion.v1_14_1);
protocolManager.registerProtocol(new Protocol1_14_1To1_14_2(), ProtocolVersion.v1_14_1, ProtocolVersion.v1_14_2);
protocolManager.registerProtocol(new Protocol1_14_2To1_14_3(), ProtocolVersion.v1_14_2, ProtocolVersion.v1_14_3);
protocolManager.registerProtocol(new Protocol1_14_3To1_14_4(), ProtocolVersion.v1_14_3, ProtocolVersion.v1_14_4);
protocolManager.registerProtocol(new Protocol1_14To1_13_2(), ProtocolVersion.v1_13_2, ProtocolVersion.v1_14);
protocolManager.registerProtocol(new Protocol1_14_1To1_14(), ProtocolVersion.v1_14, ProtocolVersion.v1_14_1);
protocolManager.registerProtocol(new Protocol1_14_2To1_14_1(), ProtocolVersion.v1_14_1, ProtocolVersion.v1_14_2);
protocolManager.registerProtocol(new Protocol1_14_3To1_14_2(), ProtocolVersion.v1_14_2, ProtocolVersion.v1_14_3);
protocolManager.registerProtocol(new Protocol1_14_4To1_14_3(), ProtocolVersion.v1_14_3, ProtocolVersion.v1_14_4);
protocolManager.registerProtocol(new Protocol1_14_4To1_15(), ProtocolVersion.v1_14_4, ProtocolVersion.v1_15);
protocolManager.registerProtocol(new Protocol1_15To1_15_1(), ProtocolVersion.v1_15, ProtocolVersion.v1_15_1);
protocolManager.registerProtocol(new Protocol1_15_1To1_15_2(), ProtocolVersion.v1_15_1, ProtocolVersion.v1_15_2);
protocolManager.registerProtocol(new Protocol1_15To1_14_4(), ProtocolVersion.v1_14_4, ProtocolVersion.v1_15);
protocolManager.registerProtocol(new Protocol1_15_1To1_15(), ProtocolVersion.v1_15, ProtocolVersion.v1_15_1);
protocolManager.registerProtocol(new Protocol1_15_2To1_15_1(), ProtocolVersion.v1_15_1, ProtocolVersion.v1_15_2);
protocolManager.registerProtocol(new Protocol1_15_2To1_16(), ProtocolVersion.v1_15_2, ProtocolVersion.v1_16);
protocolManager.registerProtocol(new Protocol1_16To1_16_1(), ProtocolVersion.v1_16, ProtocolVersion.v1_16_1);
protocolManager.registerProtocol(new Protocol1_16_1To1_16_2(), ProtocolVersion.v1_16_1, ProtocolVersion.v1_16_2);
protocolManager.registerProtocol(new Protocol1_16_2To1_16_3(), ProtocolVersion.v1_16_2, ProtocolVersion.v1_16_3);
protocolManager.registerProtocol(new Protocol1_16_3To1_16_4(), ProtocolVersion.v1_16_3, ProtocolVersion.v1_16_4);
protocolManager.registerProtocol(new Protocol1_16To1_15_2(), ProtocolVersion.v1_15_2, ProtocolVersion.v1_16);
protocolManager.registerProtocol(new Protocol1_16_1To1_16(), ProtocolVersion.v1_16, ProtocolVersion.v1_16_1);
protocolManager.registerProtocol(new Protocol1_16_2To1_16_1(), ProtocolVersion.v1_16_1, ProtocolVersion.v1_16_2);
protocolManager.registerProtocol(new Protocol1_16_3To1_16_2(), ProtocolVersion.v1_16_2, ProtocolVersion.v1_16_3);
protocolManager.registerProtocol(new Protocol1_16_4To1_16_3(), ProtocolVersion.v1_16_3, ProtocolVersion.v1_16_4);
protocolManager.registerProtocol(new Protocol1_16_4To1_17(), ProtocolVersion.v1_16_4, ProtocolVersion.v1_17);
protocolManager.registerProtocol(new Protocol1_17To1_17_1(), ProtocolVersion.v1_17, ProtocolVersion.v1_17_1);
protocolManager.registerProtocol(new Protocol1_17_1To1_18(), ProtocolVersion.v1_17_1, ProtocolVersion.v1_18);
protocolManager.registerProtocol(new Protocol1_17To1_16_4(), ProtocolVersion.v1_16_4, ProtocolVersion.v1_17);
protocolManager.registerProtocol(new Protocol1_17_1To1_17(), ProtocolVersion.v1_17, ProtocolVersion.v1_17_1);
protocolManager.registerProtocol(new Protocol1_18To1_17_1(), ProtocolVersion.v1_17_1, ProtocolVersion.v1_18);
protocolManager.registerProtocol(new Protocol1_18_2To1_18(), ProtocolVersion.v1_18, ProtocolVersion.v1_18_2);
protocolManager.registerProtocol(new Protocol1_19To1_18_2(), ProtocolVersion.v1_18_2, ProtocolVersion.v1_19);
protocolManager.registerProtocol(new Protocol1_19_1To1_19(), ProtocolVersion.v1_19, ProtocolVersion.v1_19_1);
protocolManager.registerProtocol(new Protocol1_19_3To1_19_1(), ProtocolVersion.v1_19_1, ProtocolVersion.v1_19_3);
protocolManager.registerProtocol(new Protocol1_19_4To1_19_3(), ProtocolVersion.v1_19_3, ProtocolVersion.v1_19_4);
protocolManager.registerProtocol(new Protocol1_20To1_19_4(), ProtocolVersion.v1_19_4, ProtocolVersion.v1_20);
protocolManager.registerProtocol(new Protocol1_20_2To1_20(), ProtocolVersion.v1_20, ProtocolVersion.v1_20_2);
protocolManager.registerProtocol(new Protocol1_20_3To1_20_2(), ProtocolVersion.v1_20_2, ProtocolVersion.v1_20_3);
protocolManager.registerProtocol(new Protocol1_20_5To1_20_3(), ProtocolVersion.v1_20_3, ProtocolVersion.v1_20_5);
protocolManager.registerProtocol(new Protocol1_21To1_20_5(), ProtocolVersion.v1_20_5, ProtocolVersion.v1_21);
}
/**
@@ -121,16 +154,13 @@ public interface ViaBackwardsPlatform {
String vvVersion = Via.getPlatform().getPluginVersion();
if (vvVersion != null && new Version(vvVersion).compareTo(new Version(MINIMUM_VV_VERSION + "--")) < 0) {
getLogger().severe("================================");
getLogger().severe("YOUR VIAVERSION IS OUTDATED");
getLogger().severe("YOUR VIAVERSION IS OUTDATED (you are running " + vvVersion + ")");
getLogger().severe("PLEASE USE VIAVERSION " + MINIMUM_VV_VERSION + " OR NEWER");
getLogger().severe("LINK: https://ci.viaversion.com/");
getLogger().severe("VIABACKWARDS WILL NOW DISABLE");
getLogger().severe("================================");
disable();
return true;
}
return false;
}
@@ -0,0 +1,207 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.data;
import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.BiMappings;
import com.viaversion.viaversion.api.data.IdentityMappings;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.data.Mappings;
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;
import org.checkerframework.checker.nullness.qual.Nullable;
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) {
this(unmappedVersion, mappedVersion, null);
}
public BackwardsMappingData(final String unmappedVersion, final String mappedVersion, @Nullable final Class<? extends Protocol<?, ?, ?, ?>> vvProtocolClass) {
super(unmappedVersion, mappedVersion);
Preconditions.checkArgument(vvProtocolClass == null || !BackwardsProtocol.class.isAssignableFrom(vvProtocolClass));
this.vvProtocolClass = vvProtocolClass;
}
@Override
protected void loadExtras(final CompoundTag data) {
final CompoundTag itemNames = data.getCompoundTag("itemnames");
if (itemNames != 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));
}
}
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;
}
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) {
final CompoundTag nameMappings = data.getCompoundTag(key);
if (nameMappings == null) {
return null;
}
final Int2ObjectMap<String> map = new Int2ObjectArrayMap<>(nameMappings.size());
for (final Map.Entry<String, Tag> entry : nameMappings.entrySet()) {
final StringTag mappedTag = (StringTag) entry.getValue();
map.put(Integer.parseInt(entry.getKey()), mappedTag.getValue());
}
return map;
}
@Override
protected @Nullable BiMappings loadBiMappings(final CompoundTag data, final String key) {
if (key.equals("items") && vvProtocolClass != null) {
Mappings mappings = super.loadMappings(data, key);
final MappingData mappingData = Via.getManager().getProtocolManager().getProtocol(vvProtocolClass).getMappingData();
if (mappingData != null && mappingData.getItemMappings() != null) {
final BiMappings vvItemMappings = mappingData.getItemMappings();
if (mappings == null) {
mappings = new IdentityMappings(vvItemMappings.mappedSize(), vvItemMappings.size());
}
return ItemMappings.of(mappings, vvItemMappings);
}
}
return super.loadBiMappings(data, key);
}
/**
* @see #getMappedItem(int) for custom backwards mappings
*/
@Override
public int getNewItemId(final int id) {
// Don't warn on missing here
return this.itemMappings.getNewId(id);
}
@Override
public int getNewBlockId(final int id) {
// Don't warn on missing here
return this.blockMappings.getNewId(id);
}
@Override
public int getOldItemId(final int id) {
// Warn on missing
return checkValidity(id, this.itemMappings.inverse().getNewId(id), "item");
}
@Override
public int getNewAttributeId(final int id) {
return this.attributeMappings.getNewId(id);
}
public @Nullable MappedItem getMappedItem(final int id) {
return backwardsItemMappings != null ? backwardsItemMappings.get(id) : null;
}
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);
}
public @Nullable String mappedEnchantmentName(final int enchantmentId) {
if (enchantmentNames == null) {
ViaBackwards.getPlatform().getLogger().log(Level.SEVERE, "No enchantment name mappings found when requesting " + enchantmentId, new RuntimeException());
return null;
}
return enchantmentNames.get(enchantmentId);
}
public @Nullable Int2ObjectMap<MappedItem> getBackwardsItemMappings() {
return backwardsItemMappings;
}
public @Nullable Map<String, String> getBackwardsSoundMappings() {
return backwardsSoundMappings;
}
public @Nullable Class<? extends Protocol<?, ?, ?, ?>> getViaVersionProtocolClass() {
return vvProtocolClass;
}
@Override
protected Logger getLogger() {
return ViaBackwards.getPlatform().getLogger();
}
@Override
protected @Nullable CompoundTag readMappingsFile(final String name) {
return BackwardsMappingDataLoader.INSTANCE.loadNBTFromDir(name);
}
}
@@ -0,0 +1,87 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.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 java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BackwardsMappingDataLoader extends MappingDataLoader {
public static final BackwardsMappingDataLoader INSTANCE = new BackwardsMappingDataLoader(BackwardsMappingDataLoader.class, "assets/viabackwards/data/");
public BackwardsMappingDataLoader(final Class<?> dataLoaderClass, final String dataPath) {
super(dataLoaderClass, dataPath);
}
/**
* Returns nbt data from the plugin folder or packed assets.
* If a file with the same name exists in the plugin folder, the data of the original packed tag will be merged with the file's tag.
*
* @param name name of the file
* @return nbt data from the plugin folder or packed assets
*/
public @Nullable CompoundTag loadNBTFromDir(final String name) {
final CompoundTag packedData = loadNBT(name);
final File file = new File(getDataFolder(), name);
if (!file.exists()) {
return packedData;
}
getLogger().info("Loading " + name + " from plugin folder");
try {
final CompoundTag fileData = MAPPINGS_READER.read(file.toPath(), false);
return mergeTags(packedData, fileData);
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
private CompoundTag mergeTags(final CompoundTag original, final CompoundTag extra) {
for (final Map.Entry<String, Tag> entry : extra.entrySet()) {
if (entry.getValue() instanceof CompoundTag) {
// For compound tags, don't replace the entire tag
final CompoundTag originalEntry = original.getCompoundTag(entry.getKey());
if (originalEntry != null) {
mergeTags(originalEntry, (CompoundTag) entry.getValue());
continue;
}
}
original.put(entry.getKey(), entry.getValue());
}
return original;
}
@Override
public Logger getLogger() {
return ViaBackwards.getPlatform().getLogger();
}
@Override
public File getDataFolder() {
return ViaBackwards.getPlatform().getDataFolder();
}
}
@@ -1,167 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.data;
import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.gson.JsonObject;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Map;
import java.util.logging.Logger;
public class BackwardsMappings extends MappingDataBase {
private final Class<? extends Protocol> vvProtocolClass;
private Int2ObjectMap<MappedItem> backwardsItemMappings;
private Map<String, String> backwardsSoundMappings;
private Map<String, String> entityNames;
public BackwardsMappings(String oldVersion, String newVersion, @Nullable Class<? extends Protocol> vvProtocolClass) {
this(oldVersion, newVersion, vvProtocolClass, false);
}
public BackwardsMappings(String oldVersion, String newVersion, @Nullable Class<? extends Protocol> vvProtocolClass, boolean hasDiffFile) {
super(oldVersion, newVersion, hasDiffFile);
Preconditions.checkArgument(vvProtocolClass == null || !vvProtocolClass.isAssignableFrom(BackwardsProtocol.class));
this.vvProtocolClass = vvProtocolClass;
// Just re-use ViaVersion's item id map
loadItems = false;
}
@Override
protected void loadExtras(JsonObject oldMappings, JsonObject newMappings, @Nullable JsonObject diffMappings) {
if (diffMappings != null) {
JsonObject diffItems = diffMappings.getAsJsonObject("items");
if (diffItems != null) {
backwardsItemMappings = VBMappingDataLoader.loadItemMappings(oldMappings.getAsJsonObject("items"),
newMappings.getAsJsonObject("items"), diffItems, shouldWarnOnMissing("items"));
}
JsonObject diffSounds = diffMappings.getAsJsonObject("sounds");
if (diffSounds != null) {
backwardsSoundMappings = VBMappingDataLoader.objectToNamespacedMap(diffSounds);
}
JsonObject diffEntityNames = diffMappings.getAsJsonObject("entitynames");
if (diffEntityNames != null) {
entityNames = VBMappingDataLoader.objectToMap(diffEntityNames);
}
}
// Just re-use ViaVersion's item id map
if (vvProtocolClass != null) {
itemMappings = Via.getManager().getProtocolManager().getProtocol(vvProtocolClass).getMappingData().getItemMappings().inverse();
}
loadVBExtras(oldMappings, newMappings);
}
@Override
protected @Nullable Mappings loadFromArray(JsonObject oldMappings, JsonObject newMappings, @Nullable JsonObject diffMappings, String key) {
if (!oldMappings.has(key) || !newMappings.has(key)) return null;
JsonObject diff = diffMappings != null ? diffMappings.getAsJsonObject(key) : null;
return VBMappings.vbBuilder().unmapped(oldMappings.getAsJsonArray(key)).mapped(newMappings.getAsJsonArray(key))
.diffMappings(diff).warnOnMissing(shouldWarnOnMissing(key)).build();
}
@Override
protected @Nullable Mappings loadFromObject(JsonObject oldMappings, JsonObject newMappings, @Nullable JsonObject diffMappings, String key) {
if (!oldMappings.has(key) || !newMappings.has(key)) return null;
JsonObject diff = diffMappings != null ? diffMappings.getAsJsonObject(key) : null;
return VBMappings.vbBuilder().unmapped(oldMappings.getAsJsonObject(key)).mapped(newMappings.getAsJsonObject(key))
.diffMappings(diff).warnOnMissing(shouldWarnOnMissing(key)).build();
}
@Override
protected JsonObject loadDiffFile() {
return VBMappingDataLoader.loadFromDataDir("mapping-" + newVersion + "to" + oldVersion + ".json");
}
/**
* To be overridden.
*/
protected void loadVBExtras(JsonObject oldMappings, JsonObject newMappings) {
}
protected boolean shouldWarnOnMissing(String key) {
return !key.equals("blocks") && !key.equals("statistics");
}
@Override
protected Logger getLogger() {
return ViaBackwards.getPlatform().getLogger();
}
/**
* @see #getMappedItem(int) for custom backwards mappings
*/
@Override
public int getNewItemId(int id) {
// Don't warn on missing here
return this.itemMappings.get(id);
}
@Override
public int getNewBlockId(int id) {
// Don't warn on missing here
return this.blockMappings.getNewId(id);
}
@Override
public int getOldItemId(final int id) {
// Warn on missing
return checkValidity(id, this.itemMappings.inverse().get(id), "item");
}
public @Nullable MappedItem getMappedItem(int id) {
return backwardsItemMappings != null ? backwardsItemMappings.get(id) : null;
}
public @Nullable String getMappedNamedSound(String id) {
if (backwardsSoundMappings == null) {
return null;
}
if (id.indexOf(':') == -1) {
id = "minecraft:" + id;
}
return backwardsSoundMappings.get(id);
}
public @Nullable String mappedEntityName(String entityName) {
return entityNames.get(entityName);
}
public @Nullable Int2ObjectMap<MappedItem> getBackwardsItemMappings() {
return backwardsItemMappings;
}
public @Nullable Map<String, String> getBackwardsSoundMappings() {
return backwardsSoundMappings;
}
}
@@ -0,0 +1,38 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.data;
import com.viaversion.viaversion.api.data.BiMappingsBase;
import com.viaversion.viaversion.api.data.Mappings;
public final class ItemMappings extends BiMappingsBase {
private ItemMappings(final Mappings mappings, final Mappings inverse) {
super(mappings, inverse);
}
public static ItemMappings of(final Mappings mappings, final Mappings inverse) {
return new ItemMappings(mappings, inverse);
}
@Override
public void setNewId(final int id, final int mappedId) {
// Only set one-way
mappings.setNewId(id, mappedId);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,23 +17,41 @@
*/
package com.viaversion.viabackwards.api.data;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.ComponentUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
public class MappedItem {
private final int id;
private final String jsonName;
private final Tag tagName;
private final Integer customModelData;
public MappedItem(int id, String name) {
this.id = id;
this.jsonName = ChatRewriter.legacyTextToJsonString("§f" + name);
public MappedItem(final int id, final String name) {
this(id, name, null);
}
public int getId() {
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;
}
public int id() {
return id;
}
public String getJsonName() {
public String jsonName() {
return jsonName;
}
public Tag tagName() {
return tagName;
}
public @Nullable Integer customModelData() {
return customModelData;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,8 +17,8 @@
*/
package com.viaversion.viabackwards.api.data;
import com.viaversion.viabackwards.utils.Block;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.util.IdAndData;
import org.checkerframework.checker.nullness.qual.Nullable;
public class MappedLegacyBlockItem {
@@ -26,14 +26,18 @@ public class MappedLegacyBlockItem {
private final int id;
private final short data;
private final String name;
private final Block block;
private final IdAndData block;
private BlockEntityHandler blockEntityHandler;
public MappedLegacyBlockItem(int id, short data, @Nullable String name, boolean block) {
public MappedLegacyBlockItem(int id) {
this(id, (short) -1, null, Type.ITEM);
}
public MappedLegacyBlockItem(int id, short data, @Nullable String name, Type type) {
this.id = id;
this.data = data;
this.name = name != null ? "§f" + name : null;
this.block = block ? new Block(id, data) : null;
this.block = type != Type.ITEM ? data != -1 ? new IdAndData(id, data) : new IdAndData(id) : null;
}
public int getId() {
@@ -48,11 +52,7 @@ public class MappedLegacyBlockItem {
return name;
}
public boolean isBlock() {
return block != null;
}
public Block getBlock() {
public IdAndData getBlock() {
return block;
}
@@ -73,4 +73,21 @@ public class MappedLegacyBlockItem {
CompoundTag handleOrNewCompoundTag(int block, CompoundTag tag);
}
public enum Type {
ITEM("items"),
BLOCK_ITEM("block-items"),
BLOCK("blocks");
final String name;
Type(final String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
@@ -1,174 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.data;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonIOException;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.libs.gson.JsonSyntaxException;
import com.viaversion.viaversion.util.GsonUtil;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
public final class VBMappingDataLoader {
public static JsonObject loadFromDataDir(String name) {
File file = new File(ViaBackwards.getPlatform().getDataFolder(), name);
if (!file.exists()) return loadData(name);
// Load the file from the platform's directory if present
try (FileReader reader = new FileReader(file)) {
return GsonUtil.getGson().fromJson(reader, JsonObject.class);
} catch (JsonSyntaxException e) {
ViaBackwards.getPlatform().getLogger().warning(name + " is badly formatted!");
e.printStackTrace();
ViaBackwards.getPlatform().getLogger().warning("Falling back to resource's file!");
return loadData(name);
} catch (IOException | JsonIOException e) {
e.printStackTrace();
}
return null;
}
public static JsonObject loadData(String name) {
InputStream stream = VBMappingDataLoader.class.getClassLoader().getResourceAsStream("assets/viabackwards/data/" + name);
try (InputStreamReader reader = new InputStreamReader(stream)) {
return GsonUtil.getGson().fromJson(reader, JsonObject.class);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static void mapIdentifiers(int[] output, JsonObject oldIdentifiers, JsonObject newIdentifiers, JsonObject diffIdentifiers, boolean warnOnMissing) {
Object2IntMap<String> newIdentifierMap = MappingDataLoader.indexedObjectToMap(newIdentifiers);
for (Map.Entry<String, JsonElement> entry : oldIdentifiers.entrySet()) {
String key = entry.getValue().getAsString();
int mappedId = newIdentifierMap.getInt(key);
if (mappedId == -1) {
if (diffIdentifiers != null) {
// Search in diff mappings
JsonPrimitive diffValueJson = diffIdentifiers.getAsJsonPrimitive(key);
String diffValue = diffValueJson != null ? diffValueJson.getAsString() : null;
int dataIndex;
if (diffValue == null && (dataIndex = key.indexOf('[')) != -1
&& (diffValueJson = diffIdentifiers.getAsJsonPrimitive(key.substring(0, dataIndex))) != null) {
// Check for wildcard mappings
diffValue = diffValueJson.getAsString();
// Keep original properties if value ends with [
if (diffValue.endsWith("[")) {
diffValue += key.substring(dataIndex + 1);
}
}
if (diffValue != null) {
mappedId = newIdentifierMap.getInt(diffValue);
}
}
if (mappedId == -1) {
// Nothing found :(
if (warnOnMissing && !Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("No key for " + entry.getValue() + " :( ");
}
continue;
}
}
output[Integer.parseInt(entry.getKey())] = mappedId;
}
}
public static Map<String, String> objectToNamespacedMap(JsonObject object) {
Map<String, String> mappings = new HashMap<>(object.size());
for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
String key = entry.getKey();
if (key.indexOf(':') == -1) {
key = "minecraft:" + key;
}
String value = entry.getValue().getAsString();
if (value.indexOf(':') == -1) {
value = "minecraft:" + value;
}
mappings.put(key, value);
}
return mappings;
}
public static Map<String, String> objectToMap(JsonObject object) {
Map<String, String> mappings = new HashMap<>(object.size());
for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
mappings.put(entry.getKey(), entry.getValue().getAsString());
}
return mappings;
}
public static Int2ObjectMap<MappedItem> loadItemMappings(JsonObject oldMapping, JsonObject newMapping, JsonObject diffMapping, boolean warnOnMissing) {
Int2ObjectMap<MappedItem> itemMapping = new Int2ObjectOpenHashMap<>(diffMapping.size(), 0.99F);
Object2IntMap<String> newIdenfierMap = MappingDataLoader.indexedObjectToMap(newMapping);
Object2IntMap<String> oldIdenfierMap = MappingDataLoader.indexedObjectToMap(oldMapping);
for (Map.Entry<String, JsonElement> entry : diffMapping.entrySet()) {
JsonObject object = entry.getValue().getAsJsonObject();
String mappedIdName = object.getAsJsonPrimitive("id").getAsString();
int mappedId = newIdenfierMap.getInt(mappedIdName);
if (mappedId == -1) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("No key for " + mappedIdName + " :( ");
}
continue;
}
int oldId = oldIdenfierMap.getInt(entry.getKey());
if (oldId == -1) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("No old entry for " + mappedIdName + " :( ");
}
continue;
}
String name = object.getAsJsonPrimitive("name").getAsString();
itemMapping.put(oldId, new MappedItem(mappedId, name));
}
// Look for missing keys
if (warnOnMissing && !Via.getConfig().isSuppressConversionWarnings()) {
for (Object2IntMap.Entry<String> entry : oldIdenfierMap.object2IntEntrySet()) {
if (!newIdenfierMap.containsKey(entry.getKey()) && !itemMapping.containsKey(entry.getIntValue())) {
ViaBackwards.getPlatform().getLogger().warning("No item mapping for " + entry.getKey() + " :( ");
}
}
}
return itemMapping;
}
}
@@ -1,64 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.data;
import com.viaversion.viaversion.api.data.IntArrayMappings;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.api.data.Mappings;
import java.util.Arrays;
public final class VBMappings extends IntArrayMappings {
private VBMappings(final int[] oldToNew, final int mappedIds) {
super(oldToNew, mappedIds);
}
public static Mappings.Builder<VBMappings> vbBuilder() {
return new Builder(VBMappings::new);
}
public static final class Builder extends Mappings.Builder<VBMappings> {
private Builder(final MappingsSupplier<VBMappings> supplier) {
super(supplier);
}
@Override
public VBMappings build() {
final int size = this.size != -1 ? this.size : size(unmapped);
final int mappedSize = this.mappedSize != -1 ? this.mappedSize : size(mapped);
final int[] mappings = new int[size];
Arrays.fill(mappings, -1);
// Do conversion if one is an array and the other an object, otherwise directly map
if (unmapped.isJsonArray()) {
if (mapped.isJsonObject()) {
VBMappingDataLoader.mapIdentifiers(mappings, toJsonObject(unmapped.getAsJsonArray()), mapped.getAsJsonObject(), diffMappings, warnOnMissing);
} else {
// Use the normal loader
MappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonArray(), mapped.getAsJsonArray(), diffMappings, warnOnMissing);
}
} else if (mapped.isJsonArray()) {
VBMappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonObject(), toJsonObject(mapped.getAsJsonArray()), diffMappings, warnOnMissing);
} else {
VBMappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonObject(), mapped.getAsJsonObject(), diffMappings, warnOnMissing);
}
return supplier.supply(mappings, mappedSize);
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,7 +19,7 @@ package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viabackwards.api.BackwardsProtocol;
public class EntityObjectData extends EntityData {
public class EntityObjectData extends EntityReplacement {
private final int objectData;
public EntityObjectData(BackwardsProtocol<?, ?, ?, ?> protocol, String key, int id, int replacementId, int objectData) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,47 +17,47 @@
*/
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viabackwards.ViaBackwards;
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.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.ProtocolLogger;
import java.util.function.Supplier;
public class EntityPositionHandler {
public static final double RELATIVE_MOVE_FACTOR = 32 * 128;
private final EntityRewriterBase entityRewriter;
private final EntityRewriterBase<?, ?> entityRewriter;
private final Class<? extends EntityPositionStorage> storageClass;
private final Supplier<? extends EntityPositionStorage> storageSupplier;
private boolean warnedForMissingEntity;
public EntityPositionHandler(EntityRewriterBase entityRewriter,
public EntityPositionHandler(EntityRewriterBase<?, ?> entityRewriter,
Class<? extends EntityPositionStorage> storageClass, Supplier<? extends EntityPositionStorage> storageSupplier) {
this.entityRewriter = entityRewriter;
this.storageClass = storageClass;
this.storageSupplier = storageSupplier;
}
public void cacheEntityPosition(PacketWrapper wrapper, boolean create, boolean relative) throws Exception {
public void cacheEntityPosition(PacketWrapper wrapper, boolean create, boolean relative) {
cacheEntityPosition(wrapper,
wrapper.get(Type.DOUBLE, 0), wrapper.get(Type.DOUBLE, 1), wrapper.get(Type.DOUBLE, 2), create, relative);
wrapper.get(Types.DOUBLE, 0), wrapper.get(Types.DOUBLE, 1), wrapper.get(Types.DOUBLE, 2), create, relative);
}
public void cacheEntityPosition(PacketWrapper wrapper, double x, double y, double z, boolean create, boolean relative) throws Exception {
int entityId = wrapper.get(Type.VAR_INT, 0);
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! :>
ViaBackwards.getPlatform().getLogger().warning("Stored entity with id " + entityId + " missing at position: " + x + " - " + y + " - " + z + " in " + storageClass.getSimpleName());
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) {
ViaBackwards.getPlatform().getLogger().warning("DO NOT REPORT THIS TO VIA, THIS IS A PLUGIN ISSUE");
logger.warning("DO NOT REPORT THIS TO VIA, THIS IS A PLUGIN ISSUE");
} else if (!warnedForMissingEntity) {
warnedForMissingEntity = true;
ViaBackwards.getPlatform().getLogger().warning("This is very likely caused by a plugin sending a teleport packet for an entity outside of the player's range.");
logger.warning("This is very likely caused by a plugin sending a teleport packet for an entity outside of the player's range.");
}
}
return;
@@ -70,7 +70,7 @@ public class EntityPositionHandler {
} else {
positionStorage = storedEntity.get(storageClass);
if (positionStorage == null) {
ViaBackwards.getPlatform().getLogger().warning("Stored entity with id " + entityId + " missing " + storageClass.getSimpleName());
entityRewriter.protocol().getLogger().warning("Stored entity with id " + entityId + " missing " + storageClass.getSimpleName());
return;
}
}
@@ -82,7 +82,7 @@ public class EntityPositionHandler {
StoredEntityData storedEntity = entityRewriter.tracker(user).entityData(entityId);
EntityPositionStorage entityStorage;
if (storedEntity == null || (entityStorage = storedEntity.get(EntityPositionStorage.class)) == null) {
ViaBackwards.getPlatform().getLogger().warning("Untracked entity with id " + entityId + " in " + storageClass.getSimpleName());
entityRewriter.protocol().getLogger().warning("Untracked entity with id " + entityId + " in " + storageClass.getSimpleName());
return null;
}
return entityStorage;
@@ -99,8 +99,8 @@ public class EntityPositionHandler {
}
double pitch = -Math.asin(dY / r) / Math.PI * 180;
wrapper.write(Type.BYTE, (byte) (yaw * 256f / 360f));
wrapper.write(Type.BYTE, (byte) (pitch * 256f / 360f));
wrapper.write(Types.BYTE, (byte) (yaw * 256f / 360f));
wrapper.write(Types.BYTE, (byte) (pitch * 256f / 360f));
}
public static void writeFacingDegrees(PacketWrapper wrapper, double x, double y, double z, double targetX, double targetY, double targetZ) {
@@ -114,7 +114,7 @@ public class EntityPositionHandler {
}
double pitch = -Math.asin(dY / r) / Math.PI * 180;
wrapper.write(Type.FLOAT, (float) yaw);
wrapper.write(Type.FLOAT, (float) pitch);
wrapper.write(Types.FLOAT, (float) yaw);
wrapper.write(Types.FLOAT, (float) pitch);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,15 +22,15 @@ public abstract class EntityPositionStorage {
private double y;
private double z;
public double getX() {
public double x() {
return x;
}
public double getY() {
public double y() {
return y;
}
public double getZ() {
public double z() {
return z;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,44 +18,48 @@
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.util.ComponentUtil;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Locale;
public class EntityData {
public class EntityReplacement {
private final BackwardsProtocol<?, ?, ?, ?> protocol;
private final int id;
private final int replacementId;
private final String key;
private NameVisibility nameVisibility = NameVisibility.NONE;
private ComponentType componentType = ComponentType.NONE;
private MetaCreator defaultMeta;
public EntityData(BackwardsProtocol<?, ?, ?, ?> protocol, EntityType type, int replacementId) {
public EntityReplacement(BackwardsProtocol<?, ?, ?, ?> protocol, EntityType type, int replacementId) {
this(protocol, type.name(), type.getId(), replacementId);
}
public EntityData(BackwardsProtocol<?, ?, ?, ?> protocol, String key, int id, int 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);
}
public EntityData jsonName() {
this.nameVisibility = NameVisibility.JSON;
public EntityReplacement jsonName() {
this.componentType = ComponentType.JSON;
return this;
}
public EntityData plainName() {
this.nameVisibility = NameVisibility.PLAIN;
public EntityReplacement tagName() {
this.componentType = ComponentType.TAG;
return this;
}
public EntityData spawnMetadata(MetaCreator handler) {
public EntityReplacement plainName() {
this.componentType = ComponentType.PLAIN;
return this;
}
public EntityReplacement spawnMetadata(MetaCreator handler) {
this.defaultMeta = handler;
return this;
}
@@ -71,17 +75,22 @@ public class EntityData {
/**
* @return custom mobname, can be either a String or a JsonElement
*/
public @Nullable Object mobName() {
if (nameVisibility == NameVisibility.NONE) {
public @Nullable Object entityName() {
if (componentType == ComponentType.NONE) {
return null;
}
String name = protocol.getMappingData().mappedEntityName(key);
final String name = protocol.getMappingData().mappedEntityName(key);
if (name == null) {
ViaBackwards.getPlatform().getLogger().warning("Entity name for " + key + " not found in protocol " + protocol.getClass().getSimpleName());
name = key;
return null;
}
return nameVisibility == NameVisibility.JSON ? ChatRewriter.legacyTextToJson(name) : name;
if (componentType == ComponentType.JSON) {
return ComponentUtil.legacyToJson(name);
} else if (componentType == ComponentType.TAG) {
return new StringTag(name);
}
return name;
}
public int replacementId() {
@@ -103,11 +112,11 @@ public class EntityData {
@Override
public String toString() {
return "EntityData{" +
"id=" + id +
", mobName='" + key + '\'' +
", replacementId=" + replacementId +
", defaultMeta=" + defaultMeta +
'}';
"id=" + id +
", mobName='" + key + '\'' +
", replacementId=" + replacementId +
", defaultMeta=" + defaultMeta +
'}';
}
@FunctionalInterface
@@ -116,9 +125,10 @@ public class EntityData {
void createMeta(WrappedMetadata storage);
}
private enum NameVisibility {
private enum ComponentType {
PLAIN,
JSON,
TAG,
NONE
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,7 +19,7 @@ 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.Type;
import com.viaversion.viaversion.api.type.Types;
public abstract class PlayerPositionStorage implements StorableObject {
private double x;
@@ -29,15 +29,15 @@ public abstract class PlayerPositionStorage implements StorableObject {
protected PlayerPositionStorage() {
}
public double getX() {
public double x() {
return x;
}
public double getY() {
public double y() {
return y;
}
public double getZ() {
public double z() {
return z;
}
@@ -53,8 +53,8 @@ public abstract class PlayerPositionStorage implements StorableObject {
this.z = z;
}
public void setCoordinates(PacketWrapper wrapper, boolean relative) throws Exception {
setCoordinates(wrapper.get(Type.DOUBLE, 0), wrapper.get(Type.DOUBLE, 1), wrapper.get(Type.DOUBLE, 2), relative);
public void setCoordinates(PacketWrapper wrapper, boolean relative) {
setCoordinates(wrapper.get(Types.DOUBLE, 0), wrapper.get(Types.DOUBLE, 1), wrapper.get(Types.DOUBLE, 2), relative);
}
public void setCoordinates(double x, double y, double z, boolean relative) {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,23 +18,17 @@
package com.viaversion.viabackwards.api.entities.storage;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
public record WrappedMetadata(List<EntityData> metadataList) {
public final class WrappedMetadata {
private final List<Metadata> metadataList;
public WrappedMetadata(List<Metadata> metadataList) {
this.metadataList = metadataList;
}
public boolean has(Metadata data) {
public boolean has(EntityData data) {
return this.metadataList.contains(data);
}
public void remove(Metadata data) {
public void remove(EntityData data) {
this.metadataList.remove(data);
}
@@ -42,25 +36,16 @@ public final class WrappedMetadata {
metadataList.removeIf(meta -> meta.id() == index);
}
public void add(Metadata data) {
public void add(EntityData data) {
this.metadataList.add(data);
}
public @Nullable Metadata get(int index) {
for (Metadata meta : this.metadataList) {
public @Nullable EntityData get(int index) {
for (EntityData meta : this.metadataList) {
if (index == meta.id()) {
return meta;
}
}
return null;
}
public List<Metadata> metadataList() {
return metadataList;
}
@Override
public String toString() {
return "MetaStorage{" + "metaDataList=" + metadataList + '}';
}
}
@@ -0,0 +1,125 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
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.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.MappedItem;
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 org.checkerframework.checker.nullness.qual.Nullable;
public class BackwardsItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends BackwardsProtocol<C, ?, ?, S>> extends BackwardsItemRewriterBase<C, S, T> {
public BackwardsItemRewriter(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType) {
super(protocol, itemType, itemArrayType, true);
}
public BackwardsItemRewriter(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType, Type<Item> mappedItemType, Type<Item[]> mappedItemArrayType) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType, true);
}
@Override
public @Nullable Item handleItemToClient(UserConnection connection, @Nullable Item item) {
if (item == null) {
return null;
}
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);
}
ListTag<StringTag> lore = display.getListTag("Lore", StringTag.class);
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");
}
loreEntry.setValue(newValue);
}
}
}
MappedItem data = protocol.getMappingData() != null ? protocol.getMappingData().getMappedItem(item.identifier()) : null;
if (data == null) {
// Just rewrite the id
return super.handleItemToClient(connection, item);
}
if (item.tag() == null) {
item.setTag(new CompoundTag());
}
// Save original id, set remapped id
item.tag().putInt(nbtTagName("id"), item.identifier());
item.setIdentifier(data.id());
// Add custom model data
if (data.customModelData() != null && !item.tag().contains("CustomModelData")) {
item.tag().putInt("CustomModelData", data.customModelData());
}
// Set custom name - only done if there is no original one
if (display == null) {
item.tag().put("display", display = new CompoundTag());
}
if (!display.contains("Name")) {
display.put("Name", new StringTag(data.jsonName()));
display.put(nbtTagName("customName"), new ByteTag(false));
}
return item;
}
@Override
public @Nullable Item handleItemToServer(UserConnection connection, @Nullable Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
if (item.tag() != null) {
Tag originalId = item.tag().remove(nbtTagName("id"));
if (originalId instanceof IntTag) {
item.setIdentifier(((NumberTag) originalId).asInt());
}
}
return item;
}
}
@@ -0,0 +1,113 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.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,
T extends BackwardsProtocol<C, ?, ?, S>> extends ItemRewriter<C, S, T> {
protected final boolean jsonNameFormat;
protected BackwardsItemRewriterBase(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType, Type<Item> mappedItemType, Type<Item[]> mappedItemArrayType, boolean jsonFormat) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType);
this.jsonNameFormat = jsonFormat;
}
protected BackwardsItemRewriterBase(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType, boolean jsonNameFormat) {
this(protocol, itemType, itemArrayType, itemType, itemArrayType, jsonNameFormat);
}
@Override
public @Nullable Item handleItemToServer(UserConnection connection, @Nullable Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
restoreDisplayTag(item);
return item;
}
protected boolean hasBackupTag(CompoundTag tag, String tagName) {
return tag.contains(nbtTagName(tagName));
}
protected void saveStringTag(CompoundTag tag, StringTag original, String name) {
// Multiple places might try to backup data
String backupName = nbtTagName(name);
if (!tag.contains(backupName)) {
tag.putString(backupName, original.getValue());
}
}
protected void saveListTag(CompoundTag tag, ListTag<?> original, String name) {
// Multiple places might try to backup data
String backupName = nbtTagName(name);
if (!tag.contains(backupName)) {
tag.put(backupName, original.copy());
}
}
protected void restoreDisplayTag(Item item) {
if (item.tag() == null) return;
CompoundTag display = item.tag().getCompoundTag("display");
if (display != null) {
// Remove custom name / restore original name
if (display.remove(nbtTagName("customName")) != null) {
display.remove("Name");
} else {
restoreStringTag(display, "Name");
}
// Restore lore
restoreListTag(display, "Lore");
}
}
protected void restoreStringTag(CompoundTag tag, String tagName) {
Tag original = tag.remove(nbtTagName(tagName));
if (original instanceof StringTag) {
tag.putString(tagName, ((StringTag) original).getValue());
}
}
protected void restoreListTag(CompoundTag tag, String tagName) {
Tag original = tag.remove(nbtTagName(tagName));
if (original instanceof ListTag) {
tag.put(tagName, ((ListTag<?>) original).copy());
}
}
@Override
public String nbtTagName() {
return "VB|" + protocol.getClass().getSimpleName();
}
}
@@ -0,0 +1,217 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viabackwards.api.data.MappedItem;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
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.type.Type;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntFunction;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public class BackwardsStructuredItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends BackwardsProtocol<C, ?, ?, S>> extends StructuredItemRewriter<C, S, T> {
public BackwardsStructuredItemRewriter(final T protocol, final Type<Item> itemType, final Type<Item[]> itemArrayType) {
super(protocol, itemType, itemArrayType);
}
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);
}
@Override
public Item handleItemToClient(final UserConnection connection, final Item item) {
if (item.isEmpty()) {
return item;
}
final StructuredDataContainer dataContainer = item.dataContainer();
final BackwardsMappingData mappingData = protocol.getMappingData();
if (mappingData != null && mappingData.getDataComponentSerializerMappings() != null) {
final FullMappings mappings = mappingData.getDataComponentSerializerMappings();
dataContainer.setIdLookup(protocol, true);
dataContainer.updateIds(protocol, mappings::getNewId);
}
if (protocol.getComponentRewriter() != null) {
// Handle name and lore components
final StructuredData<Tag> customNameData = dataContainer.getNonEmpty(StructuredDataKey.CUSTOM_NAME);
if (customNameData != null) {
final Tag originalName = customNameData.value().copy();
protocol.getComponentRewriter().processTag(connection, customNameData.value());
if (!customNameData.value().equals(originalName)) {
saveTag(createCustomTag(item), originalName, "Name");
}
}
final StructuredData<Tag[]> loreData = dataContainer.getNonEmpty(StructuredDataKey.LORE);
if (loreData != null) {
for (final Tag tag : loreData.value()) {
protocol.getComponentRewriter().processTag(connection, tag);
}
}
}
Int2IntFunction itemIdRewriter = null;
Int2IntFunction blockIdRewriter = null;
if (mappingData != null) {
itemIdRewriter = mappingData.getItemMappings() != null ? mappingData::getNewItemId : null;
blockIdRewriter = mappingData.getBlockMappings() != null ? mappingData::getNewBlockId : null;
}
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()));
}
updateItemComponents(connection, dataContainer, this::handleItemToClient, itemIdRewriter, blockIdRewriter);
return item;
}
// Save original id, set remapped id
final CompoundTag tag = createCustomTag(item);
tag.putInt(nbtTagName("id"), item.identifier());
item.setIdentifier(mappedItem.id());
// Add custom model data
if (mappedItem.customModelData() != null && !dataContainer.contains(StructuredDataKey.CUSTOM_MODEL_DATA)) {
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA, mappedItem.customModelData());
}
// Set custom name - only done if there is no original one
if (!dataContainer.contains(StructuredDataKey.CUSTOM_NAME)) {
dataContainer.set(StructuredDataKey.CUSTOM_NAME, mappedItem.tagName());
tag.putBoolean(nbtTagName("customName"), true);
}
updateItemComponents(connection, dataContainer, this::handleItemToClient, itemIdRewriter, blockIdRewriter);
return item;
}
@Override
public Item handleItemToServer(final UserConnection connection, final Item item) {
if (item.isEmpty()) {
return item;
}
final BackwardsMappingData mappingData = protocol.getMappingData();
final StructuredDataContainer dataContainer = item.dataContainer();
if (mappingData != null) {
if (mappingData.getItemMappings() != null) {
item.setIdentifier(mappingData.getOldItemId(item.identifier()));
}
final FullMappings dataComponentMappings = mappingData.getDataComponentSerializerMappings();
if (dataComponentMappings != null) {
dataContainer.setIdLookup(protocol, false);
dataContainer.updateIds(protocol, id -> dataComponentMappings.inverse().getNewId(id));
}
}
final CompoundTag tag = customTag(item);
if (tag != null) {
final Tag originalId = tag.remove(nbtTagName("id"));
if (originalId instanceof IntTag) {
item.setIdentifier(((NumberTag) originalId).asInt());
}
}
restoreTextComponents(item);
Int2IntFunction itemIdRewriter = null;
Int2IntFunction blockIdRewriter = null;
if (mappingData != null) {
itemIdRewriter = mappingData.getItemMappings() != null ? mappingData::getOldItemId : null;
blockIdRewriter = mappingData.getBlockMappings() != null ? mappingData::getOldBlockId : null;
}
updateItemComponents(connection, dataContainer, this::handleItemToServer, itemIdRewriter, blockIdRewriter);
return item;
}
protected @Nullable CompoundTag customTag(final Item item) {
final StructuredData<CompoundTag> customData = item.dataContainer().getNonEmpty(StructuredDataKey.CUSTOM_DATA);
return customData != null ? customData.value() : null;
}
protected void saveListTag(CompoundTag tag, ListTag<?> original, String name) {
// Multiple places might try to backup data
String backupName = nbtTagName(name);
if (!tag.contains(backupName)) {
tag.put(backupName, original.copy());
}
}
public <T extends Tag> @Nullable ListTag<T> removeListTag(CompoundTag tag, String tagName, Class<T> tagType) {
String backupName = nbtTagName(tagName);
ListTag<T> data = tag.getListTag(backupName, tagType);
if (data == null) {
return null;
}
tag.remove(backupName);
return data;
}
protected void saveGenericTagList(CompoundTag tag, List<Tag> original, String name) {
// List tags cannot contain tags of different types, so we have to store them a bit more awkwardly as an indexed compound tag
String backupName = nbtTagName(name);
if (!tag.contains(backupName)) {
CompoundTag output = new CompoundTag();
for (int i = 0; i < original.size(); i++) {
output.put(Integer.toString(i), original.get(i));
}
tag.put(backupName, output);
}
}
protected List<Tag> removeGenericTagList(CompoundTag tag, String name) {
String backupName = nbtTagName(name);
CompoundTag data = tag.getCompoundTag(backupName);
if (data == null) {
return null;
}
tag.remove(backupName);
return new ArrayList<>(data.values());
}
@Override
public String nbtTagName() {
return "VB|" + protocol.getClass().getSimpleName();
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,14 +18,12 @@
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ShortTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
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.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.Key;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -37,31 +35,31 @@ import java.util.Map;
*/
public class EnchantmentRewriter {
private final Map<String, String> enchantmentMappings = new HashMap<>();
private final ItemRewriter itemRewriter;
protected final Map<String, String> enchantmentMappings = new HashMap<>();
protected final BackwardsItemRewriter<?, ?, ?> itemRewriter;
private final boolean jsonFormat;
public EnchantmentRewriter(ItemRewriter itemRewriter, boolean jsonFormat) {
public EnchantmentRewriter(BackwardsItemRewriter<?, ?, ?> itemRewriter, boolean jsonFormat) {
this.itemRewriter = itemRewriter;
this.jsonFormat = jsonFormat;
}
public EnchantmentRewriter(ItemRewriter itemRewriter) {
public EnchantmentRewriter(BackwardsItemRewriter<?, ?, ?> itemRewriter) {
this(itemRewriter, true);
}
public void registerEnchantment(String key, String replacementLore) {
enchantmentMappings.put(key, replacementLore);
enchantmentMappings.put(Key.stripMinecraftNamespace(key), replacementLore);
}
public void handleToClient(Item item) {
CompoundTag tag = item.tag();
if (tag == null) return;
if (tag.get("Enchantments") instanceof ListTag) {
if (tag.getListTag("Enchantments") != null) {
rewriteEnchantmentsToClient(tag, false);
}
if (tag.get("StoredEnchantments") instanceof ListTag) {
if (tag.getListTag("StoredEnchantments") != null) {
rewriteEnchantmentsToClient(tag, true);
}
}
@@ -70,27 +68,29 @@ public class EnchantmentRewriter {
CompoundTag tag = item.tag();
if (tag == null) return;
if (tag.contains(itemRewriter.getNbtTagName() + "|Enchantments")) {
if (tag.contains(itemRewriter.nbtTagName("Enchantments"))) {
rewriteEnchantmentsToServer(tag, false);
}
if (tag.contains(itemRewriter.getNbtTagName() + "|StoredEnchantments")) {
if (tag.contains(itemRewriter.nbtTagName("StoredEnchantments"))) {
rewriteEnchantmentsToServer(tag, true);
}
}
public void rewriteEnchantmentsToClient(CompoundTag tag, boolean storedEnchant) {
String key = storedEnchant ? "StoredEnchantments" : "Enchantments";
ListTag enchantments = tag.get(key);
List<Tag> loreToAdd = new ArrayList<>();
ListTag<CompoundTag> enchantments = tag.getListTag(key, CompoundTag.class);
List<StringTag> loreToAdd = new ArrayList<>();
boolean changed = false;
Iterator<Tag> iterator = enchantments.iterator();
Iterator<CompoundTag> iterator = enchantments.iterator();
while (iterator.hasNext()) {
CompoundTag enchantmentEntry = (CompoundTag) iterator.next();
Tag idTag = enchantmentEntry.get("id");
if (!(idTag instanceof StringTag)) continue;
CompoundTag enchantmentEntry = iterator.next();
StringTag idTag = enchantmentEntry.getStringTag("id");
if (idTag == null) {
continue;
}
String enchantmentId = ((StringTag) idTag).getValue();
String enchantmentId = Key.stripMinecraftNamespace(idTag.getValue());
String remappedName = enchantmentMappings.get(enchantmentId);
if (remappedName != null) {
if (!changed) {
@@ -101,10 +101,11 @@ public class EnchantmentRewriter {
iterator.remove();
int level = ((NumberTag) enchantmentEntry.get("lvl")).asInt();
NumberTag levelTag = enchantmentEntry.getNumberTag("lvl");
int level = levelTag != null ? levelTag.asInt() : 1;
String loreValue = remappedName + " " + getRomanNumber(level);
if (jsonFormat) {
loreValue = ChatRewriter.legacyTextToJsonString(loreValue);
loreValue = ComponentUtil.legacyToJsonString(loreValue);
}
loreToAdd.add(new StringTag(loreValue));
@@ -113,21 +114,21 @@ public class EnchantmentRewriter {
if (!loreToAdd.isEmpty()) {
// Add dummy enchant for the glow effect if there are no actual enchantments left
if (!storedEnchant && enchantments.size() == 0) {
if (!storedEnchant && enchantments.isEmpty()) {
CompoundTag dummyEnchantment = new CompoundTag();
dummyEnchantment.put("id", new StringTag());
dummyEnchantment.put("lvl", new ShortTag((short) 0));
dummyEnchantment.putString("id", "");
dummyEnchantment.putShort("lvl", (short) 0);
enchantments.add(dummyEnchantment);
}
CompoundTag display = tag.get("display");
CompoundTag display = tag.getCompoundTag("display");
if (display == null) {
tag.put("display", display = new CompoundTag());
}
ListTag loreTag = display.get("Lore");
ListTag<StringTag> loreTag = display.getListTag("Lore", StringTag.class);
if (loreTag == null) {
display.put("Lore", loreTag = new ListTag(StringTag.class));
display.put("Lore", loreTag = new ListTag<>(StringTag.class));
} else {
// Save original lore
itemRewriter.saveListTag(display, loreTag, "Lore");
@@ -145,29 +146,18 @@ public class EnchantmentRewriter {
}
public static String getRomanNumber(int number) {
switch (number) {
case 1:
return "I";
case 2:
return "II";
case 3:
return "III";
case 4:
return "IV";
case 5:
return "V";
case 6:
return "VI";
case 7:
return "VII";
case 8:
return "VIII";
case 9:
return "IX";
case 10:
return "X";
default:
return Integer.toString(number);
}
return switch (number) {
case 1 -> "I";
case 2 -> "II";
case 3 -> "III";
case 4 -> "IV";
case 5 -> "V";
case 6 -> "VI";
case 7 -> "VII";
case 8 -> "VIII";
case 9 -> "IX";
case 10 -> "X";
default -> Integer.toString(number);
};
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,75 +18,135 @@
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.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
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.protocol.remapper.PacketRemapper;
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.api.type.types.version.Types1_14;
public abstract class EntityRewriter<T extends BackwardsProtocol> extends EntityRewriterBase<T> {
public abstract class EntityRewriter<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends EntityRewriterBase<C, T> {
protected EntityRewriter(T protocol) {
this(protocol, Types1_14.META_TYPES.optionalComponentType, Types1_14.META_TYPES.booleanType);
this(protocol, Types1_14.ENTITY_DATA_TYPES.optionalComponentType, Types1_14.ENTITY_DATA_TYPES.booleanType);
}
protected EntityRewriter(T protocol, MetaType displayType, MetaType displayVisibilityType) {
protected EntityRewriter(T protocol, EntityDataType displayType, EntityDataType displayVisibilityType) {
super(protocol, displayType, 2, displayVisibilityType, 3);
}
@Override
public void registerTrackerWithData(ClientboundPacketType packetType, EntityType fallingBlockType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
public void registerTrackerWithData(C packetType, EntityType fallingBlockType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - Entity UUID
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - Data
public void register() {
map(Types.VAR_INT); // 0 - Entity id
map(Types.UUID); // 1 - Entity UUID
map(Types.VAR_INT); // 2 - Entity Type
map(Types.DOUBLE); // 3 - X
map(Types.DOUBLE); // 4 - Y
map(Types.DOUBLE); // 5 - Z
map(Types.BYTE); // 6 - Pitch
map(Types.BYTE); // 7 - Yaw
map(Types.INT); // 8 - Data
handler(getSpawnTrackerWithDataHandler(fallingBlockType));
}
});
}
@Override
public void registerTrackerWithData1_19(C packetType, EntityType fallingBlockType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // Entity id
map(Types.UUID); // Entity UUID
map(Types.VAR_INT); // Entity type
map(Types.DOUBLE); // X
map(Types.DOUBLE); // Y
map(Types.DOUBLE); // Z
map(Types.BYTE); // Pitch
map(Types.BYTE); // Yaw
map(Types.BYTE); // Head yaw
map(Types.VAR_INT); // Data
handler(getSpawnTrackerWithDataHandler1_19(fallingBlockType));
}
});
}
public PacketHandler getSpawnTrackerWithDataHandler(EntityType fallingBlockType) {
return wrapper -> {
// Check against the UNMAPPED entity type
EntityType entityType = setOldEntityId(wrapper);
EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) {
int blockState = wrapper.get(Type.INT, 0);
wrapper.set(Type.INT, 0, protocol.getMappingData().getNewBlockStateId(blockState));
int blockState = wrapper.get(Types.INT, 0);
wrapper.set(Types.INT, 0, protocol.getMappingData().getNewBlockStateId(blockState));
}
};
}
public void registerSpawnTracker(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
public PacketHandler getSpawnTrackerWithDataHandler1_19(EntityType fallingBlockType) {
return wrapper -> {
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, new PacketHandlers() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Entity UUID
map(Type.VAR_INT); // 2 - Entity Type
handler(wrapper -> setOldEntityId(wrapper));
public void register() {
map(Types.VAR_INT); // 0 - Entity ID
map(Types.UUID); // 1 - Entity UUID
map(Types.VAR_INT); // 2 - Entity Type
handler(wrapper -> trackAndMapEntity(wrapper));
}
});
}
private EntityType setOldEntityId(PacketWrapper wrapper) throws Exception {
int typeId = wrapper.get(Type.VAR_INT, 1);
/**
* 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.trackClientEntity();
}
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 typeId = wrapper.get(Types.VAR_INT, 1);
EntityType entityType = typeFromId(typeId);
tracker(wrapper.user()).addEntity(wrapper.get(Type.VAR_INT, 0), entityType);
tracker(wrapper.user()).addEntity(wrapper.get(Types.VAR_INT, 0), entityType);
int mappedTypeId = newEntityId(entityType.getId());
if (typeId != mappedTypeId) {
wrapper.set(Type.VAR_INT, 1, 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-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,25 +20,27 @@ package com.viaversion.viabackwards.api.rewriters;
import com.google.common.base.Preconditions;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.entities.storage.EntityData;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
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.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntOpenHashMap;
import com.viaversion.viaversion.api.type.Types;
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.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.rewriter.meta.MetaHandlerEvent;
import org.checkerframework.checker.nullness.qual.Nullable;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEvent;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Entity rewriter base class.
@@ -46,16 +48,15 @@ import java.util.List;
* @see com.viaversion.viabackwards.api.rewriters.EntityRewriter
* @see LegacyEntityRewriter
*/
public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends EntityRewriter<T> {
private final Int2ObjectMap<EntityData> entityDataMappings = new Int2ObjectOpenHashMap<>();
private final MetaType displayNameMetaType;
private final MetaType displayVisibilityMetaType;
public abstract class EntityRewriterBase<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends EntityRewriter<C, T> {
private final Int2ObjectMap<EntityReplacement> entityDataMappings = new Int2ObjectOpenHashMap<>();
private final EntityDataType displayNameMetaType;
private final EntityDataType displayVisibilityMetaType;
private final int displayNameIndex;
private final int displayVisibilityIndex;
protected boolean allowNullEntityType;
EntityRewriterBase(T protocol, MetaType displayNameMetaType, int displayNameIndex,
MetaType displayVisibilityMetaType, int displayVisibilityIndex) {
EntityRewriterBase(T protocol, EntityDataType displayNameMetaType, int displayNameIndex,
EntityDataType displayVisibilityMetaType, int displayVisibilityIndex) {
super(protocol, false);
this.displayNameMetaType = displayNameMetaType;
this.displayNameIndex = displayNameIndex;
@@ -64,41 +65,61 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends En
}
@Override
public void handleMetadata(int entityId, List<Metadata> metadataList, UserConnection connection) {
EntityType type = tracker(connection).entityType(entityId);
if (type == null && !allowNullEntityType) {
return;
}
public void handleEntityData(int entityId, List<EntityData> entityDataList, UserConnection connection) {
final TrackedEntity entity = tracker(connection).entity(entityId);
final boolean initialMetadata = !(entity != null && entity.hasSentEntityData());
super.handleMetadata(entityId, metadataList, connection);
super.handleEntityData(entityId, entityDataList, connection);
if (type == null) {
if (entity == null) {
return; // Don't handle untracked entities - basically always the fault of a plugin sending virtual entities through concurrency-unsafe handling
}
EntityData entityData = entityDataForType(type);
// Set the mapped entity name if there is no custom name set already
Metadata meta = getMeta(displayNameIndex, metadataList);
if (meta != null && entityData != null && entityData.mobName() != null
&& (meta.getValue() == null || meta.getValue().toString().isEmpty())
&& meta.metaType().typeId() == displayNameMetaType.typeId()) {
meta.setValue(entityData.mobName());
if (ViaBackwards.getConfig().alwaysShowOriginalMobName()) {
removeMeta(displayVisibilityIndex, metadataList);
metadataList.add(new Metadata(displayVisibilityIndex, displayVisibilityMetaType, true));
final EntityReplacement entityMapping = entityDataForType(entity.entityType());
final Object displayNameObject;
if (entityMapping != null && (displayNameObject = entityMapping.entityName()) != null) {
final EntityData displayName = getData(displayNameIndex, entityDataList);
if (initialMetadata) {
if (displayName == null) {
// Add it as new metadata
entityDataList.add(new EntityData(displayNameIndex, displayNameMetaType, displayNameObject));
addDisplayVisibilityMeta(entityDataList);
} else if (displayName.getValue() == null || displayName.getValue().toString().isEmpty()) {
// Overwrite the existing null/empty display name
displayName.setValue(displayNameObject);
addDisplayVisibilityMeta(entityDataList);
}
} else if (displayName != null && (displayName.getValue() == null || displayName.getValue().toString().isEmpty())) {
// Overwrite null/empty display name
displayName.setValue(displayNameObject);
addDisplayVisibilityMeta(entityDataList);
}
}
// Add any other extra meta for mapped entities
//TODO only do this once for a first meta packet?
if (entityData != null && entityData.hasBaseMeta()) {
entityData.defaultMeta().createMeta(new WrappedMetadata(metadataList));
if (entityMapping != null && entityMapping.hasBaseMeta() && initialMetadata) {
entityMapping.defaultMeta().createMeta(new WrappedMetadata(entityDataList));
}
}
protected @Nullable Metadata getMeta(int metaIndex, List<Metadata> metadataList) {
for (Metadata metadata : metadataList) {
private void addDisplayVisibilityMeta(List<EntityData> metadataList) {
if (alwaysShowOriginalMobName()) {
removeMeta(displayVisibilityIndex, metadataList);
metadataList.add(new EntityData(displayVisibilityIndex, displayVisibilityMetaType, getDisplayVisibilityMetaValue()));
}
}
protected Object getDisplayVisibilityMetaValue() {
return true;
}
protected boolean alwaysShowOriginalMobName() {
return ViaBackwards.getConfig().alwaysShowOriginalMobName();
}
protected @Nullable EntityData getData(int metaIndex, List<EntityData> metadataList) {
for (EntityData metadata : metadataList) {
if (metadata.id() == metaIndex) {
return metadata;
}
@@ -106,7 +127,7 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends En
return null;
}
protected void removeMeta(int metaIndex, List<Metadata> metadataList) {
protected void removeMeta(int metaIndex, List<EntityData> metadataList) {
metadataList.removeIf(meta -> meta.id() == metaIndex);
}
@@ -114,11 +135,11 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends En
return entityDataMappings.containsKey(type.getId());
}
protected @Nullable EntityData entityDataForType(EntityType type) {
protected @Nullable EntityReplacement entityDataForType(EntityType type) {
return entityDataMappings.get(type.getId());
}
protected @Nullable StoredEntityData storedEntityData(MetaHandlerEvent event) {
protected @Nullable StoredEntityData storedEntityData(EntityDataHandlerEvent event) {
return tracker(event.user()).entityData(event.entityId());
}
@@ -131,55 +152,76 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends En
* @return created entity data
* @see #mapEntityType(EntityType, EntityType) for id only rewriting
*/
protected EntityData mapEntityTypeWithData(EntityType type, EntityType mappedType) {
Preconditions.checkArgument(type.getClass() == mappedType.getClass());
protected EntityReplacement mapEntityTypeWithData(EntityType type, EntityType mappedType) {
Preconditions.checkArgument(type.getClass() == mappedType.getClass(), "Both entity types need to be of the same class");
// Already rewrite the id here
int mappedReplacementId = newEntityId(mappedType.getId());
EntityData data = new EntityData(protocol, type, mappedReplacementId);
EntityReplacement data = new EntityReplacement(protocol, type, mappedReplacementId);
mapEntityType(type.getId(), mappedReplacementId);
entityDataMappings.put(type.getId(), data);
return data;
}
/**
* Maps entity ids based on the enum constant's names.
*
* @param oldTypes entity types of the higher version
* @param newTypeClass entity types enum class of the lower version
* @param <E> new enum type
*/
@Override
public <E extends Enum<E> & EntityType> void mapTypes(EntityType[] oldTypes, Class<E> newTypeClass) {
if (typeMappings == null) {
typeMappings = new Int2IntOpenHashMap(oldTypes.length, 0.99F);
typeMappings.defaultReturnValue(-1);
}
for (EntityType oldType : oldTypes) {
try {
E newType = Enum.valueOf(newTypeClass, oldType.name());
typeMappings.put(oldType.getId(), newType.getId());
} catch (IllegalArgumentException ignored) {
// Don't warn
}
}
}
public void registerMetaTypeHandler(@Nullable MetaType itemType, @Nullable MetaType blockType, @Nullable MetaType particleType, @Nullable MetaType optChatType) {
public void registerMetaTypeHandler(
@Nullable EntityDataType itemType,
@Nullable EntityDataType blockStateType,
@Nullable EntityDataType optionalBlockStateType,
@Nullable EntityDataType particleType,
@Nullable EntityDataType componentType,
@Nullable EntityDataType optionalComponentType
) {
filter().handler((event, meta) -> {
MetaType type = meta.metaType();
if (itemType != null && type == itemType) {
protocol.getItemRewriter().handleItemToClient(meta.value());
} else if (blockType != null && type == blockType) {
EntityDataType type = meta.dataType();
if (type == itemType) {
protocol.getItemRewriter().handleItemToClient(event.user(), meta.value());
} else if (type == blockStateType) {
int data = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
} else if (particleType != null && type == particleType) {
rewriteParticle(meta.value());
} else if (optChatType != null && type == optChatType) {
JsonElement text = meta.value();
if (text != null) {
protocol.getTranslatableRewriter().processText(text);
} else if (type == optionalBlockStateType) {
int data = meta.value();
if (data != 0) {
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
}
} else if (type == particleType) {
rewriteParticle(event.user(), meta.value());
} else if (type == optionalComponentType || type == componentType) {
JsonElement text = meta.value();
protocol.getComponentRewriter().processText(event.user(), text);
}
});
}
public void registerMetaTypeHandler1_20_3(
@Nullable EntityDataType itemType,
@Nullable EntityDataType blockStateType,
@Nullable EntityDataType optionalBlockStateType,
@Nullable EntityDataType particleType,
@Nullable EntityDataType particlesType,
@Nullable EntityDataType componentType,
@Nullable EntityDataType optionalComponentType
) {
filter().handler((event, meta) -> {
EntityDataType type = meta.dataType();
if (type == itemType) {
meta.setValue(protocol.getItemRewriter().handleItemToClient(event.user(), meta.value()));
} else if (type == blockStateType) {
int data = meta.value();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
} else if (type == optionalBlockStateType) {
int data = meta.value();
if (data != 0) {
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
}
} else if (type == particleType) {
rewriteParticle(event.user(), meta.value());
} else if (type == particlesType) {
Particle[] particles = meta.value();
for (final Particle particle : particles) {
rewriteParticle(event.user(), particle);
}
} else if (type == optionalComponentType || type == componentType) {
protocol.getComponentRewriter().processTag(event.user(), meta.value());
}
});
}
@@ -188,12 +230,12 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends En
protected PacketHandler getTrackerHandler(Type<? extends Number> intType, int typeIndex) {
return wrapper -> {
Number id = wrapper.get(intType, typeIndex);
tracker(wrapper.user()).addEntity(wrapper.get(Type.VAR_INT, 0), typeFromId(id.intValue()));
tracker(wrapper.user()).addEntity(wrapper.get(Types.VAR_INT, 0), typeFromId(id.intValue()));
};
}
protected PacketHandler getTrackerHandler() {
return getTrackerHandler(Type.VAR_INT, 1);
return getTrackerHandler(Types.VAR_INT, 1);
}
protected PacketHandler getTrackerHandler(EntityType entityType, Type<? extends Number> intType) {
@@ -203,7 +245,7 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends En
protected PacketHandler getDimensionHandler(int index) {
return wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
int dimensionId = wrapper.get(Type.INT, index);
int dimensionId = wrapper.get(Types.INT, index);
clientWorld.setEnvironment(dimensionId);
};
}
@@ -1,114 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.MappedItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ByteTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class ItemRewriter<T extends BackwardsProtocol> extends ItemRewriterBase<T> {
private final TranslatableRewriter translatableRewriter;
protected ItemRewriter(T protocol, @Nullable TranslatableRewriter translatableRewriter) {
super(protocol, true);
this.translatableRewriter = translatableRewriter;
}
@Override
public @Nullable Item handleItemToClient(@Nullable Item item) {
if (item == null) return null;
CompoundTag display = item.tag() != null ? item.tag().get("display") : null;
if (translatableRewriter != null && display != null) {
// Handle name and lore components
StringTag name = display.get("Name");
if (name != null) {
String newValue = translatableRewriter.processText(name.getValue()).toString();
if (!newValue.equals(name.getValue())) {
saveStringTag(display, name, "Name");
}
name.setValue(newValue);
}
ListTag lore = display.get("Lore");
if (lore != null) {
boolean changed = false;
for (Tag loreEntryTag : lore) {
if (!(loreEntryTag instanceof StringTag)) continue;
StringTag loreEntry = (StringTag) loreEntryTag;
String newValue = translatableRewriter.processText(loreEntry.getValue()).toString();
if (!changed && !newValue.equals(loreEntry.getValue())) {
// Backup original lore before doing any modifications
changed = true;
saveListTag(display, lore, "Lore");
}
loreEntry.setValue(newValue);
}
}
}
MappedItem data = protocol.getMappingData().getMappedItem(item.identifier());
if (data == null) {
// Just rewrite the id
return super.handleItemToClient(item);
}
if (item.tag() == null) {
item.setTag(new CompoundTag());
}
// Save original id, set remapped id
item.tag().put(nbtTagName + "|id", new IntTag(item.identifier()));
item.setIdentifier(data.getId());
// Set custom name - only done if there is no original one
if (display == null) {
item.tag().put("display", display = new CompoundTag());
}
if (!display.contains("Name")) {
display.put("Name", new StringTag(data.getJsonName()));
display.put(nbtTagName + "|customName", new ByteTag());
}
return item;
}
@Override
public @Nullable Item handleItemToServer(@Nullable Item item) {
if (item == null) return null;
super.handleItemToServer(item);
if (item.tag() != null) {
IntTag originalId = item.tag().remove(nbtTagName + "|id");
if (originalId != null) {
item.setIdentifier(originalId.asInt());
}
}
return item;
}
}
@@ -1,108 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.rewriter.ItemRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class ItemRewriterBase<T extends BackwardsProtocol> extends ItemRewriter<T> {
protected final String nbtTagName;
protected final boolean jsonNameFormat;
protected ItemRewriterBase(T protocol, boolean jsonNameFormat) {
super(protocol);
this.jsonNameFormat = jsonNameFormat;
nbtTagName = "VB|" + protocol.getClass().getSimpleName();
}
public @Nullable Item handleItemToServer(@Nullable Item item) {
if (item == null) return null;
super.handleItemToServer(item);
restoreDisplayTag(item);
return item;
}
protected boolean hasBackupTag(CompoundTag displayTag, String tagName) {
return displayTag.contains(nbtTagName + "|o" + tagName);
}
protected void saveStringTag(CompoundTag displayTag, StringTag original, String name) {
// Multiple places might try to backup data
String backupName = nbtTagName + "|o" + name;
if (!displayTag.contains(backupName)) {
displayTag.put(backupName, new StringTag(original.getValue()));
}
}
protected void saveListTag(CompoundTag displayTag, ListTag original, String name) {
// Multiple places might try to backup data
String backupName = nbtTagName + "|o" + name;
if (!displayTag.contains(backupName)) {
// Clone all tag entries
ListTag listTag = new ListTag();
for (Tag tag : original.getValue()) {
listTag.add(tag.clone());
}
displayTag.put(backupName, listTag);
}
}
protected void restoreDisplayTag(Item item) {
if (item.tag() == null) return;
CompoundTag display = item.tag().get("display");
if (display != null) {
// Remove custom name / restore original name
if (display.remove(nbtTagName + "|customName") != null) {
display.remove("Name");
} else {
restoreStringTag(display, "Name");
}
// Restore lore
restoreListTag(display, "Lore");
}
}
protected void restoreStringTag(CompoundTag tag, String tagName) {
StringTag original = tag.remove(nbtTagName + "|o" + tagName);
if (original != null) {
tag.put(tagName, new StringTag(original.getValue()));
}
}
protected void restoreListTag(CompoundTag tag, String tagName) {
ListTag original = tag.remove(nbtTagName + "|o" + tagName);
if (original != null) {
tag.put(tagName, new ListTag(original.getValue()));
}
}
public String getNbtTagName() {
return nbtTagName;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,135 +20,232 @@ package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.MappedLegacyBlockItem;
import com.viaversion.viabackwards.api.data.VBMappingDataLoader;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.data.BlockColors;
import com.viaversion.viabackwards.utils.Block;
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
import com.viaversion.viabackwards.protocol.v1_12to1_11_1.data.BlockColors1_11_1;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_12;
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.remapper.PacketHandler;
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.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ByteTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.ShortTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.ComponentUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.viaversion.viaversion.util.IdAndData;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class LegacyBlockItemRewriter<T extends BackwardsProtocol> extends ItemRewriterBase<T> {
public abstract class LegacyBlockItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends BackwardsProtocol<C, ?, ?, S>> extends BackwardsItemRewriterBase<C, S, T> {
private static final Map<String, Int2ObjectMap<MappedLegacyBlockItem>> LEGACY_MAPPINGS = new HashMap<>();
protected final Int2ObjectMap<MappedLegacyBlockItem> replacementData;
protected final Int2ObjectMap<MappedLegacyBlockItem> itemReplacements = new Int2ObjectOpenHashMap<>(8); // Raw id -> mapped data
protected final Int2ObjectMap<MappedLegacyBlockItem> blockReplacements = new Int2ObjectOpenHashMap<>(8); // Raw id -> mapped data
static {
JsonObject jsonObject = VBMappingDataLoader.loadFromDataDir("legacy-mappings.json");
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
Int2ObjectMap<MappedLegacyBlockItem> mappings = new Int2ObjectOpenHashMap<>(8);
LEGACY_MAPPINGS.put(entry.getKey(), mappings);
for (Map.Entry<String, JsonElement> dataEntry : entry.getValue().getAsJsonObject().entrySet()) {
JsonObject object = dataEntry.getValue().getAsJsonObject();
int id = object.getAsJsonPrimitive("id").getAsInt();
JsonPrimitive jsonData = object.getAsJsonPrimitive("data");
short data = jsonData != null ? jsonData.getAsShort() : 0;
String name = object.getAsJsonPrimitive("name").getAsString();
JsonPrimitive blockField = object.getAsJsonPrimitive("block");
boolean block = blockField != null && blockField.getAsBoolean();
protected LegacyBlockItemRewriter(T protocol, String name, Type<Item> itemType, Type<Item[]> itemArrayType, Type<Item> mappedItemType, Type<Item[]> mappedItemArrayType) {
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType, false);
if (dataEntry.getKey().indexOf('-') != -1) {
// Range of ids
String[] split = dataEntry.getKey().split("-", 2);
int from = Integer.parseInt(split[0]);
int to = Integer.parseInt(split[1]);
Int2ObjectMap<MappedLegacyBlockItem> blockItemReplacements = new Int2ObjectOpenHashMap<>(8);
final JsonObject jsonObject = readMappingsFile("item-mappings-" + name + ".json");
addMappings(MappedLegacyBlockItem.Type.ITEM, jsonObject, itemReplacements);
addMappings(MappedLegacyBlockItem.Type.BLOCK_ITEM, jsonObject, blockItemReplacements);
addMappings(MappedLegacyBlockItem.Type.BLOCK, jsonObject, blockReplacements);
// Special block color handling
if (name.contains("%color%")) {
for (int i = from; i <= to; i++) {
mappings.put(i, new MappedLegacyBlockItem(id, data, name.replace("%color%", BlockColors.get(i - from)), block));
}
} else {
MappedLegacyBlockItem mappedBlockItem = new MappedLegacyBlockItem(id, data, name, block);
for (int i = from; i <= to; i++) {
mappings.put(i, mappedBlockItem);
}
}
} else {
mappings.put(Integer.parseInt(dataEntry.getKey()), new MappedLegacyBlockItem(id, data, name, block));
}
blockReplacements.putAll(blockItemReplacements);
itemReplacements.putAll(blockItemReplacements);
}
protected LegacyBlockItemRewriter(T protocol, String name, Type<Item> itemType, Type<Item[]> itemArrayType) {
this(protocol, name, itemType, itemArrayType, itemType, itemArrayType);
}
protected LegacyBlockItemRewriter(T protocol, String name) {
this(protocol, name, Types.ITEM1_8, Types.ITEM1_8_SHORT_ARRAY);
}
private void addMappings(MappedLegacyBlockItem.Type type, JsonObject object, Int2ObjectMap<MappedLegacyBlockItem> mappings) {
if (object.has(type.getName())) {
final JsonObject mappingsObject = object.getAsJsonObject(type.getName());
for (Map.Entry<String, JsonElement> dataEntry : mappingsObject.entrySet()) {
addMapping(dataEntry.getKey(), dataEntry.getValue().getAsJsonObject(), type, mappings);
}
}
}
protected LegacyBlockItemRewriter(T protocol) {
super(protocol, false);
replacementData = LEGACY_MAPPINGS.get(protocol.getClass().getSimpleName().split("To")[1].replace("_", "."));
private void addMapping(String key, JsonObject object, MappedLegacyBlockItem.Type type, Int2ObjectMap<MappedLegacyBlockItem> mappings) {
int id = object.getAsJsonPrimitive("id").getAsInt();
JsonPrimitive jsonData = object.getAsJsonPrimitive("data");
short data = jsonData != null ? jsonData.getAsShort() : 0;
String name = type != MappedLegacyBlockItem.Type.BLOCK ? object.getAsJsonPrimitive("name").getAsString() : null;
if (key.indexOf('-') == -1) {
int unmappedId;
int dataSeparatorIndex = key.indexOf(':');
if (dataSeparatorIndex != -1) {
// Include data
short unmappedData = Short.parseShort(key.substring(dataSeparatorIndex + 1));
unmappedId = Integer.parseInt(key.substring(0, dataSeparatorIndex));
unmappedId = IdAndData.toRawData(unmappedId, unmappedData);
} else {
unmappedId = IdAndData.toRawData(Integer.parseInt(key), -1);
}
mappings.put(unmappedId, new MappedLegacyBlockItem(id, data, name, type));
return;
}
// Range of ids
String[] split = key.split("-", 2);
int from = Integer.parseInt(split[0]);
int to = Integer.parseInt(split[1]);
// Special block color handling
if (name != null && name.contains("%color%")) {
for (int i = from; i <= to; i++) {
mappings.put(IdAndData.toRawData(i, -1), new MappedLegacyBlockItem(id, data, name.replace("%color%", BlockColors1_11_1.get(i - from)), type));
}
} else {
MappedLegacyBlockItem mappedBlockItem = new MappedLegacyBlockItem(id, data, name, type);
for (int i = from; i <= to; i++) {
mappings.put(IdAndData.toRawData(i, -1), mappedBlockItem);
}
}
}
public void registerBlockChange(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Types.BLOCK_POSITION1_8); // 0 - Block Position
map(Types.VAR_INT); // 1 - Block
handler(wrapper -> {
int idx = wrapper.get(Types.VAR_INT, 0);
wrapper.set(Types.VAR_INT, 0, handleBlockId(idx));
});
}
});
}
public void registerMultiBlockChange(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // 0 - Chunk X
map(Types.INT); // 1 - Chunk Z
map(Types.BLOCK_CHANGE_ARRAY);
handler(wrapper -> {
for (BlockChangeRecord record : wrapper.get(Types.BLOCK_CHANGE_ARRAY, 0)) {
record.setBlockId(handleBlockId(record.getBlockId()));
}
});
}
});
}
@Override
public @Nullable Item handleItemToClient(@Nullable Item item) {
public @Nullable Item handleItemToClient(UserConnection connection, @Nullable Item item) {
if (item == null) return null;
MappedLegacyBlockItem data = replacementData.get(item.identifier());
MappedLegacyBlockItem data = getMappedItem(item.identifier(), item.data());
if (data == null) {
// Just rewrite the id
return super.handleItemToClient(item);
return super.handleItemToClient(connection, item);
}
if (item.tag() == null) {
item.setTag(new CompoundTag());
}
short originalData = item.data();
item.tag().putInt(nbtTagName("id"), item.identifier());
item.setIdentifier(data.getId());
// Keep original data if mapped data is set to -1
if (data.getData() != -1) {
item.setData(data.getData());
item.tag().putShort(nbtTagName("data"), originalData);
}
// Set display name
if (data.getName() != null) {
if (item.tag() == null) {
item.setTag(new CompoundTag());
}
CompoundTag display = item.tag().get("display");
CompoundTag display = item.tag().getCompoundTag("display");
if (display == null) {
item.tag().put("display", display = new CompoundTag());
}
StringTag nameTag = display.get("Name");
StringTag nameTag = display.getStringTag("Name");
if (nameTag == null) {
display.put("Name", nameTag = new StringTag(data.getName()));
display.put(nbtTagName + "|customName", new ByteTag());
nameTag = new StringTag(data.getName());
display.put("Name", nameTag);
display.put(nbtTagName("customName"), new ByteTag(false));
}
// Handle colors
String value = nameTag.getValue();
if (value.contains("%vb_color%")) {
display.put("Name", new StringTag(value.replace("%vb_color%", BlockColors.get(originalData))));
display.putString("Name", value.replace("%vb_color%", BlockColors1_11_1.get(originalData)));
}
}
return item;
}
public int handleBlockID(int idx) {
int type = idx >> 4;
int meta = idx & 15;
Block b = handleBlock(type, meta);
if (b == null) return idx;
return (b.getId() << 4 | (b.getData() & 15));
@Override
public @Nullable Item handleItemToServer(UserConnection connection, @Nullable final Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
if (item.tag() != null) {
Tag originalId = item.tag().remove(nbtTagName("id"));
if (originalId instanceof IntTag) {
item.setIdentifier(((NumberTag) originalId).asInt());
}
Tag originalData = item.tag().remove(nbtTagName("data"));
if (originalData instanceof ShortTag) {
item.setData(((NumberTag) originalData).asShort());
}
}
return item;
}
public @Nullable Block handleBlock(int blockId, int data) {
MappedLegacyBlockItem settings = replacementData.get(blockId);
if (settings == null || !settings.isBlock()) return null;
public PacketHandler getFallingBlockHandler() {
return wrapper -> {
final EntityTypes1_12.ObjectType type = EntityTypes1_12.ObjectType.findById(wrapper.get(Types.BYTE, 0));
if (type == EntityTypes1_12.ObjectType.FALLING_BLOCK) {
final int objectData = wrapper.get(Types.INT, 0);
Block block = settings.getBlock();
final IdAndData block = handleBlock(objectData & 4095, objectData >> 12 & 15);
if (block == null) return;
wrapper.set(Types.INT, 0, block.getId() | block.getData() << 12);
}
};
}
public @Nullable IdAndData handleBlock(int blockId, int data) {
MappedLegacyBlockItem settings = getMappedBlock(blockId, data);
if (settings == null) {
return null;
}
IdAndData block = settings.getBlock();
// For some blocks, the data can still be useful (:
if (block.getData() == -1) {
return block.withData(data);
@@ -156,33 +253,41 @@ public abstract class LegacyBlockItemRewriter<T extends BackwardsProtocol> exten
return block;
}
protected void handleChunk(Chunk chunk) {
public int handleBlockId(final int rawId) {
final int id = IdAndData.getId(rawId);
final int data = IdAndData.getData(rawId);
final IdAndData mappedBlock = handleBlock(id, data);
if (mappedBlock == null) return rawId;
return IdAndData.toRawData(mappedBlock.getId(), mappedBlock.getData());
}
public void handleChunk(Chunk chunk) {
// Map Block Entities
Map<Pos, CompoundTag> tags = new HashMap<>();
for (CompoundTag tag : chunk.getBlockEntities()) {
Tag xTag;
Tag yTag;
Tag zTag;
if ((xTag = tag.get("x")) == null || (yTag = tag.get("y")) == null || (zTag = tag.get("z")) == null) {
NumberTag xTag;
NumberTag yTag;
NumberTag zTag;
if ((xTag = tag.getNumberTag("x")) == null
|| (yTag = tag.getNumberTag("y")) == null
|| (zTag = tag.getNumberTag("z")) == null) {
continue;
}
Pos pos = new Pos(
((NumberTag) xTag).asInt() & 0xF,
((NumberTag) yTag).asInt(),
((NumberTag) zTag).asInt() & 0xF);
Pos pos = new Pos(xTag.asInt() & 0xF, yTag.asInt(), zTag.asInt() & 0xF);
tags.put(pos, tag);
// Handle given Block Entities
if (pos.getY() < 0 || pos.getY() > 255) continue; // 1.17
if (pos.y() < 0 || pos.y() > 255) continue; // 1.17
ChunkSection section = chunk.getSections()[pos.getY() >> 4];
ChunkSection section = chunk.getSections()[pos.y() >> 4];
if (section == null) continue;
int block = section.getFlatBlock(pos.getX(), pos.getY() & 0xF, pos.getZ());
int btype = block >> 4;
int block = section.palette(PaletteType.BLOCKS).idAt(pos.x(), pos.y() & 0xF, pos.z());
MappedLegacyBlockItem settings = replacementData.get(btype);
MappedLegacyBlockItem settings = getMappedBlock(block);
if (settings != null && settings.hasBlockEntityHandler()) {
settings.getBlockEntityHandler().handleOrNewCompoundTag(block, tag);
}
@@ -190,25 +295,28 @@ public abstract class LegacyBlockItemRewriter<T extends BackwardsProtocol> exten
for (int i = 0; i < chunk.getSections().length; i++) {
ChunkSection section = chunk.getSections()[i];
if (section == null) continue;
if (section == null) {
continue;
}
boolean hasBlockEntityHandler = false;
// Map blocks
for (int j = 0; j < section.getPaletteSize(); j++) {
int block = section.getPaletteEntry(j);
DataPalette palette = section.palette(PaletteType.BLOCKS);
for (int j = 0; j < palette.size(); j++) {
int block = palette.idByIndex(j);
int btype = block >> 4;
int meta = block & 0xF;
Block b = handleBlock(btype, meta);
IdAndData b = handleBlock(btype, meta);
if (b != null) {
section.setPaletteEntry(j, (b.getId() << 4) | (b.getData() & 0xF));
palette.setIdByIndex(j, IdAndData.toRawData(b.getId(), b.getData()));
}
// We already know that is has a handler
if (hasBlockEntityHandler) continue;
MappedLegacyBlockItem settings = replacementData.get(btype);
MappedLegacyBlockItem settings = getMappedBlock(block);
if (settings != null && settings.hasBlockEntityHandler()) {
hasBlockEntityHandler = true;
}
@@ -220,11 +328,9 @@ public abstract class LegacyBlockItemRewriter<T extends BackwardsProtocol> exten
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
int block = section.getFlatBlock(x, y, z);
int btype = block >> 4;
int meta = block & 15;
int block = palette.idAt(x, y, z);
MappedLegacyBlockItem settings = replacementData.get(btype);
MappedLegacyBlockItem settings = getMappedBlock(block);
if (settings == null || !settings.hasBlockEntityHandler()) continue;
Pos pos = new Pos(x, (y + (i << 4)), z);
@@ -233,9 +339,9 @@ public abstract class LegacyBlockItemRewriter<T extends BackwardsProtocol> exten
if (tags.containsKey(pos)) continue;
CompoundTag tag = new CompoundTag();
tag.put("x", new IntTag(x + (chunk.getX() << 4)));
tag.put("y", new IntTag(y + (i << 4)));
tag.put("z", new IntTag(z + (chunk.getZ() << 4)));
tag.putInt("x", x + (chunk.getX() << 4));
tag.putInt("y", y + (i << 4));
tag.putInt("z", z + (chunk.getZ() << 4));
settings.getBlockEntityHandler().handleOrNewCompoundTag(block, tag);
chunk.getBlockEntities().add(tag);
@@ -247,57 +353,37 @@ public abstract class LegacyBlockItemRewriter<T extends BackwardsProtocol> exten
protected CompoundTag getNamedTag(String text) {
CompoundTag tag = new CompoundTag();
tag.put("display", new CompoundTag());
CompoundTag displayTag = new CompoundTag();
tag.put("display", displayTag);
text = "§r" + text;
((CompoundTag) tag.get("display")).put("Name", new StringTag(jsonNameFormat ? ChatRewriter.legacyTextToJsonString(text) : text));
displayTag.putString("Name", jsonNameFormat ? ComponentUtil.legacyToJsonString(text) : text);
return tag;
}
private static final class Pos {
private @Nullable MappedLegacyBlockItem getMappedBlock(int id, int data) {
MappedLegacyBlockItem mapping = blockReplacements.get(IdAndData.toRawData(id, data));
return mapping != null ? mapping : blockReplacements.get(IdAndData.toRawData(id, -1));
}
private final int x;
private final short y;
private final int z;
private @Nullable MappedLegacyBlockItem getMappedItem(int id, int data) {
MappedLegacyBlockItem mapping = itemReplacements.get(IdAndData.toRawData(id, data));
return mapping != null ? mapping : itemReplacements.get(IdAndData.toRawData(id, -1));
}
private Pos(int x, int y, int z) {
this.x = x;
this.y = (short) y;
this.z = z;
}
private @Nullable MappedLegacyBlockItem getMappedBlock(int rawId) {
int id = IdAndData.getId(rawId);
int data = IdAndData.getData(rawId);
return getMappedBlock(id, data);
}
public int getX() {
return x;
}
protected JsonObject readMappingsFile(final String name) {
return BackwardsMappingDataLoader.INSTANCE.loadFromDataDir(name);
}
public int getY() {
return y;
}
private record Pos(int x, short y, int z) {
public int getZ() {
return z;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pos pos = (Pos) o;
if (x != pos.x) return false;
if (y != pos.y) return false;
return z == pos.z;
}
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
result = 31 * result + z;
return result;
}
@Override
public String toString() {
return "Pos{" + "x=" + x + ", y=" + y + ", z=" + z + '}';
public Pos(int x, int y, int z) {
this(x, (short) y, z);
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,15 +17,14 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ByteTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ShortTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
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;
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 java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -37,30 +36,62 @@ public class LegacyEnchantmentRewriter {
private final Map<Short, String> enchantmentMappings = new HashMap<>();
private final String nbtTagName;
private final boolean dummyEnchantment;
private Set<Short> hideLevelForEnchants;
public LegacyEnchantmentRewriter(String nbtTagName) {
this(nbtTagName, true);
}
public LegacyEnchantmentRewriter(String nbtTagName, boolean dummyEnchantment) {
this.nbtTagName = nbtTagName;
this.dummyEnchantment = dummyEnchantment;
}
public void registerEnchantment(int id, String replacementLore) {
enchantmentMappings.put((short) id, replacementLore);
}
public void handleToClient(Item item) {
CompoundTag tag = item.tag();
if (tag == null) return;
if (tag.getListTag("ench") != null) {
rewriteEnchantmentsToClient(tag, false);
}
if (tag.getListTag("StoredEnchantments") != null) {
rewriteEnchantmentsToClient(tag, true);
}
}
public void handleToServer(Item item) {
CompoundTag tag = item.tag();
if (tag == null) return;
if (tag.getListTag(nbtTagName + "|ench", CompoundTag.class) != null) {
rewriteEnchantmentsToServer(tag, false);
}
if (tag.getListTag(nbtTagName + "|StoredEnchantments", CompoundTag.class) != null) {
rewriteEnchantmentsToServer(tag, true);
}
}
public void rewriteEnchantmentsToClient(CompoundTag tag, boolean storedEnchant) {
String key = storedEnchant ? "StoredEnchantments" : "ench";
ListTag enchantments = tag.get(key);
ListTag remappedEnchantments = new ListTag(CompoundTag.class);
List<Tag> lore = new ArrayList<>();
for (Tag enchantmentEntry : enchantments.clone()) {
Tag idTag = ((CompoundTag) enchantmentEntry).get("id");
ListTag<CompoundTag> enchantments = tag.getListTag(key, CompoundTag.class);
ListTag<CompoundTag> remappedEnchantments = new ListTag<>(CompoundTag.class);
List<StringTag> lore = new ArrayList<>();
for (CompoundTag enchantmentEntry : enchantments.copy()) {
NumberTag idTag = enchantmentEntry.getNumberTag("id");
if (idTag == null) continue;
short newId = ((NumberTag) idTag).asShort();
short newId = idTag.asShort();
String enchantmentName = enchantmentMappings.get(newId);
if (enchantmentName != null) {
enchantments.remove(enchantmentEntry);
short level = ((NumberTag) ((CompoundTag) enchantmentEntry).get("lvl")).asShort();
NumberTag levelTag = enchantmentEntry.getNumberTag("lvl");
short level = levelTag != null ? levelTag.asShort() : 1;
if (hideLevelForEnchants != null && hideLevelForEnchants.contains(newId)) {
lore.add(new StringTag(enchantmentName));
} else {
@@ -70,35 +101,34 @@ public class LegacyEnchantmentRewriter {
}
}
if (!lore.isEmpty()) {
if (!storedEnchant && enchantments.size() == 0) {
if (this.dummyEnchantment && !storedEnchant && enchantments.isEmpty()) {
CompoundTag dummyEnchantment = new CompoundTag();
dummyEnchantment.put("id", new ShortTag((short) 0));
dummyEnchantment.put("lvl", new ShortTag((short) 0));
dummyEnchantment.putShort("id", (short) 0);
dummyEnchantment.putShort("lvl", (short) 0);
enchantments.add(dummyEnchantment);
tag.put(nbtTagName + "|dummyEnchant", new ByteTag(false));
tag.put(nbtTagName + "|dummyEnchant", new ByteTag());
IntTag hideFlags = tag.get("HideFlags");
NumberTag hideFlags = tag.getNumberTag("HideFlags");
if (hideFlags == null) {
hideFlags = new IntTag();
} else {
tag.put(nbtTagName + "|oldHideFlags", new IntTag(hideFlags.asByte()));
tag.putInt(nbtTagName + "|oldHideFlags", hideFlags.asByte());
}
int flags = hideFlags.asByte() | 1;
hideFlags.setValue(flags);
tag.put("HideFlags", hideFlags);
tag.putInt("HideFlags", flags);
}
tag.put(nbtTagName + "|" + key, remappedEnchantments);
CompoundTag display = tag.get("display");
CompoundTag display = tag.getCompoundTag("display");
if (display == null) {
tag.put("display", display = new CompoundTag());
}
ListTag loreTag = display.get("Lore");
ListTag<StringTag> loreTag = display.getListTag("Lore", StringTag.class);
if (loreTag == null) {
display.put("Lore", loreTag = new ListTag(StringTag.class));
display.put("Lore", loreTag = new ListTag<>(StringTag.class));
}
lore.addAll(loreTag.getValue());
@@ -108,39 +138,41 @@ public class LegacyEnchantmentRewriter {
public void rewriteEnchantmentsToServer(CompoundTag tag, boolean storedEnchant) {
String key = storedEnchant ? "StoredEnchantments" : "ench";
ListTag remappedEnchantments = tag.remove(nbtTagName + "|" + key);
ListTag enchantments = tag.get(key);
ListTag<CompoundTag> enchantments = tag.getListTag(key, CompoundTag.class);
if (enchantments == null) {
enchantments = new ListTag(CompoundTag.class);
enchantments = new ListTag<>(CompoundTag.class);
}
if (!storedEnchant && tag.remove(nbtTagName + "|dummyEnchant") != null) {
for (Tag enchantment : enchantments.clone()) {
short id = ((NumberTag) ((CompoundTag) enchantment).get("id")).asShort();
short level = ((NumberTag) ((CompoundTag) enchantment).get("lvl")).asShort();
for (CompoundTag enchantment : enchantments.copy()) {
NumberTag idTag = enchantment.getNumberTag("id");
NumberTag levelTag = enchantment.getNumberTag("lvl");
short id = idTag != null ? idTag.asShort() : 0;
short level = levelTag != null ? levelTag.asShort() : 0;
if (id == 0 && level == 0) {
enchantments.remove(enchantment);
}
}
IntTag hideFlags = tag.remove(nbtTagName + "|oldHideFlags");
if (hideFlags != null) {
tag.put("HideFlags", new IntTag(hideFlags.asByte()));
Tag hideFlags = tag.remove(nbtTagName + "|oldHideFlags");
if (hideFlags instanceof IntTag intTag) {
tag.putInt("HideFlags", intTag.asByte());
} else {
tag.remove("HideFlags");
}
}
CompoundTag display = tag.get("display");
CompoundTag display = tag.getCompoundTag("display");
// A few null checks just to be safe, though they shouldn't actually be
ListTag lore = display != null ? display.get("Lore") : null;
for (Tag enchantment : remappedEnchantments.clone()) {
ListTag<StringTag> lore = display != null ? display.getListTag("Lore", StringTag.class) : null;
ListTag<CompoundTag> remappedEnchantments = (ListTag<CompoundTag>) tag.remove(nbtTagName + "|" + key);
for (CompoundTag enchantment : remappedEnchantments.copy()) {
enchantments.add(enchantment);
if (lore != null && lore.size() != 0) {
if (lore != null && !lore.isEmpty()) {
lore.remove(lore.get(0));
}
}
if (lore != null && lore.size() == 0) {
if (lore != null && lore.isEmpty()) {
display.remove("Lore");
if (display.isEmpty()) {
tag.remove("display");
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,37 +17,36 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.entities.storage.EntityData;
import com.viaversion.viabackwards.api.entities.storage.EntityReplacement;
import com.viaversion.viabackwards.api.entities.storage.EntityObjectData;
import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.ObjectType;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_9;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_9;
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.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import org.checkerframework.checker.nullness.qual.Nullable;
import com.viaversion.viaversion.api.type.Types;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class LegacyEntityRewriter<T extends BackwardsProtocol> extends EntityRewriterBase<T> {
private final Map<ObjectType, EntityData> objectTypes = new HashMap<>();
public abstract class LegacyEntityRewriter<C extends ClientboundPacketType, T extends BackwardsProtocol<C, ?, ?, ?>> extends EntityRewriterBase<C, T> {
private final Map<ObjectType, EntityReplacement> objectTypes = new HashMap<>();
protected LegacyEntityRewriter(T protocol) {
this(protocol, MetaType1_9.String, MetaType1_9.Boolean);
this(protocol, EntityDataTypes1_9.STRING, EntityDataTypes1_9.BOOLEAN);
}
protected LegacyEntityRewriter(T protocol, MetaType displayType, MetaType displayVisibilityType) {
protected LegacyEntityRewriter(T protocol, EntityDataType displayType, EntityDataType displayVisibilityType) {
super(protocol, displayType, 2, displayVisibilityType, 3);
}
@@ -57,117 +56,127 @@ public abstract class LegacyEntityRewriter<T extends BackwardsProtocol> extends
return entData;
}
protected @Nullable EntityData getObjectData(ObjectType type) {
protected @Nullable EntityReplacement getObjectData(ObjectType type) {
return objectTypes.get(type);
}
protected void registerRespawn(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
protected void registerRespawn(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void registerMap() {
map(Type.INT);
public void register() {
map(Types.INT);
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
clientWorld.setEnvironment(wrapper.get(Type.INT, 0));
clientWorld.setEnvironment(wrapper.get(Types.INT, 0));
});
}
});
}
protected void registerJoinGame(ClientboundPacketType packetType, EntityType playerType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
protected void registerJoinGame(C packetType, EntityType playerType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Entity ID
map(Type.UNSIGNED_BYTE); // 1 - Gamemode
map(Type.INT); // 2 - Dimension
public void register() {
map(Types.INT); // 0 - Entity ID
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
map(Types.INT); // 2 - Dimension
handler(wrapper -> {
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
clientChunks.setEnvironment(wrapper.get(Type.INT, 1));
addTrackedEntity(wrapper, wrapper.get(Type.INT, 0), playerType);
clientChunks.setEnvironment(wrapper.get(Types.INT, 1));
addTrackedEntity(wrapper, wrapper.get(Types.INT, 0), playerType);
});
}
});
}
@Override
public void registerMetadataRewriter(ClientboundPacketType packetType, Type<List<Metadata>> oldMetaType, Type<List<Metadata>> newMetaType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
public void registerSetEntityData(C packetType, Type<List<EntityData>> oldMetaType, Type<List<EntityData>> newMetaType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
public void register() {
map(Types.VAR_INT); // 0 - Entity ID
if (oldMetaType != null) {
map(oldMetaType, newMetaType);
} else {
map(newMetaType);
}
handler(wrapper -> {
List<Metadata> metadata = wrapper.get(newMetaType, 0);
handleMetadata(wrapper.get(Type.VAR_INT, 0), metadata, wrapper.user());
List<EntityData> metadata = wrapper.get(newMetaType, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), metadata, wrapper.user());
});
}
});
}
@Override
public void registerMetadataRewriter(ClientboundPacketType packetType, Type<List<Metadata>> metaType) {
registerMetadataRewriter(packetType, null, metaType);
public void registerSetEntityData(C packetType, Type<List<EntityData>> metaType) {
registerSetEntityData(packetType, null, metaType);
}
protected PacketHandler getMobSpawnRewriter(Type<List<Metadata>> metaType) {
protected PacketHandler getMobSpawnRewriter(Type<List<EntityData>> metaType, IdSetter idSetter) {
return wrapper -> {
int entityId = wrapper.get(Type.VAR_INT, 0);
int entityId = wrapper.get(Types.VAR_INT, 0);
EntityType type = tracker(wrapper.user()).entityType(entityId);
List<Metadata> metadata = wrapper.get(metaType, 0);
handleMetadata(entityId, metadata, wrapper.user());
List<EntityData> metadata = wrapper.get(metaType, 0);
handleEntityData(entityId, metadata, wrapper.user());
EntityData entityData = entityDataForType(type);
if (entityData != null) {
wrapper.set(Type.VAR_INT, 1, entityData.replacementId());
if (entityData.hasBaseMeta()) {
entityData.defaultMeta().createMeta(new WrappedMetadata(metadata));
EntityReplacement entityReplacement = entityDataForType(type);
if (entityReplacement != null) {
idSetter.setId(wrapper, entityReplacement.replacementId());
if (entityReplacement.hasBaseMeta()) {
entityReplacement.defaultMeta().createMeta(new WrappedMetadata(metadata));
}
}
};
}
protected PacketHandler getObjectTrackerHandler() {
return wrapper -> addTrackedEntity(wrapper, wrapper.get(Type.VAR_INT, 0), getObjectTypeFromId(wrapper.get(Type.BYTE, 0)));
public PacketHandler getMobSpawnRewriter(Type<List<EntityData>> metaType) {
return getMobSpawnRewriter(metaType, (wrapper, id) -> wrapper.set(Types.UNSIGNED_BYTE, 0, (short) id));
}
protected PacketHandler getTrackerAndMetaHandler(Type<List<Metadata>> metaType, EntityType entityType) {
public PacketHandler getMobSpawnRewriter1_11(Type<List<EntityData>> metaType) {
return getMobSpawnRewriter(metaType, (wrapper, id) -> wrapper.set(Types.VAR_INT, 1, id));
}
protected PacketHandler getObjectTrackerHandler() {
return wrapper -> addTrackedEntity(wrapper, wrapper.get(Types.VAR_INT, 0), objectTypeFromId(wrapper.get(Types.BYTE, 0)));
}
protected PacketHandler getTrackerAndMetaHandler(Type<List<EntityData>> metaType, EntityType entityType) {
return wrapper -> {
addTrackedEntity(wrapper, wrapper.get(Type.VAR_INT, 0), entityType);
List<Metadata> metadata = wrapper.get(metaType, 0);
handleMetadata(wrapper.get(Type.VAR_INT, 0), metadata, wrapper.user());
addTrackedEntity(wrapper, wrapper.get(Types.VAR_INT, 0), entityType);
List<EntityData> metadata = wrapper.get(metaType, 0);
handleEntityData(wrapper.get(Types.VAR_INT, 0), metadata, wrapper.user());
};
}
protected PacketHandler getObjectRewriter(Function<Byte, ObjectType> objectGetter) {
return wrapper -> {
ObjectType type = objectGetter.apply(wrapper.get(Type.BYTE, 0));
ObjectType type = objectGetter.apply(wrapper.get(Types.BYTE, 0));
if (type == null) {
ViaBackwards.getPlatform().getLogger().warning("Could not find Entity Type" + wrapper.get(Type.BYTE, 0));
protocol.getLogger().warning("Could not find Entity Type" + wrapper.get(Types.BYTE, 0));
return;
}
EntityData data = getObjectData(type);
EntityReplacement data = getObjectData(type);
if (data != null) {
wrapper.set(Type.BYTE, 0, (byte) data.replacementId());
wrapper.set(Types.BYTE, 0, (byte) data.replacementId());
if (data.objectData() != -1) {
wrapper.set(Type.INT, 0, data.objectData());
wrapper.set(Types.INT, 0, data.objectData());
}
}
};
}
protected EntityType getObjectTypeFromId(int typeId) {
return typeFromId(typeId);
}
@Deprecated
protected void addTrackedEntity(PacketWrapper wrapper, int entityId, EntityType type) throws Exception {
protected void addTrackedEntity(PacketWrapper wrapper, int entityId, EntityType type) {
tracker(wrapper.user()).addEntity(entityId, type);
}
@FunctionalInterface
protected interface IdSetter {
void setId(PacketWrapper wrapper, int id);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,7 @@ import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
@Deprecated
public abstract class LegacySoundRewriter<T extends BackwardsProtocol> extends RewriterBase<T> {
public abstract class LegacySoundRewriter<T extends BackwardsProtocol<?, ?, ?, ?>> extends RewriterBase<T> {
protected final Int2ObjectMap<SoundData> soundRewrites = new Int2ObjectOpenHashMap<>(64);
protected LegacySoundRewriter(T protocol) {
@@ -50,11 +50,11 @@ public abstract class LegacySoundRewriter<T extends BackwardsProtocol> extends R
public int handleSounds(int soundId) {
int newSoundId = soundId;
SoundData data = soundRewrites.get(soundId);
if (data != null) return data.getReplacementSound();
if (data != null) return data.replacementSound();
for (Int2ObjectMap.Entry<SoundData> entry : soundRewrites.int2ObjectEntrySet()) {
if (soundId > entry.getIntKey()) {
if (entry.getValue().isAdded()) {
if (entry.getValue().added()) {
newSoundId--;
} else {
newSoundId++;
@@ -66,41 +66,14 @@ public abstract class LegacySoundRewriter<T extends BackwardsProtocol> extends R
public boolean hasPitch(int soundId) {
SoundData data = soundRewrites.get(soundId);
return data != null && data.isChangePitch();
return data != null && data.changePitch();
}
public float handlePitch(int soundId) {
SoundData data = soundRewrites.get(soundId);
return data != null ? data.getNewPitch() : 1F;
return data != null ? data.newPitch() : 1F;
}
public static final class SoundData {
private final int replacementSound;
private final boolean changePitch;
private final float newPitch;
private final boolean added;
public SoundData(int replacementSound, boolean changePitch, float newPitch, boolean added) {
this.replacementSound = replacementSound;
this.changePitch = changePitch;
this.newPitch = newPitch;
this.added = added;
}
public int getReplacementSound() {
return replacementSound;
}
public boolean isChangePitch() {
return changePitch;
}
public float getNewPitch() {
return newPitch;
}
public boolean isAdded() {
return added;
}
public record SoundData(int replacementSound, boolean changePitch, float newPitch, boolean added) {
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,6 +19,7 @@ package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.rewriter.IdRewriteFunction;
public final class MapColorRewriter {
@@ -31,24 +32,22 @@ public final class MapColorRewriter {
*/
public static PacketHandler getRewriteHandler(IdRewriteFunction rewriter) {
return wrapper -> {
int iconCount = wrapper.passthrough(Type.VAR_INT);
int iconCount = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < iconCount; i++) {
wrapper.passthrough(Type.VAR_INT); // Type
wrapper.passthrough(Type.BYTE); // X
wrapper.passthrough(Type.BYTE); // Z
wrapper.passthrough(Type.BYTE); // Direction
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.COMPONENT); // Display Name
}
wrapper.passthrough(Types.VAR_INT); // Type
wrapper.passthrough(Types.BYTE); // X
wrapper.passthrough(Types.BYTE); // Z
wrapper.passthrough(Types.BYTE); // Direction
wrapper.passthrough(Types.OPTIONAL_COMPONENT); // Display Name
}
short columns = wrapper.passthrough(Type.UNSIGNED_BYTE);
short columns = wrapper.passthrough(Types.UNSIGNED_BYTE);
if (columns < 1) return;
wrapper.passthrough(Type.UNSIGNED_BYTE); // Rows
wrapper.passthrough(Type.UNSIGNED_BYTE); // X
wrapper.passthrough(Type.UNSIGNED_BYTE); // Z
byte[] data = wrapper.passthrough(Type.BYTE_ARRAY_PRIMITIVE);
wrapper.passthrough(Types.UNSIGNED_BYTE); // Rows
wrapper.passthrough(Types.UNSIGNED_BYTE); // X
wrapper.passthrough(Types.UNSIGNED_BYTE); // Z
byte[] data = wrapper.passthrough(Types.BYTE_ARRAY_PRIMITIVE);
for (int i = 0; i < data.length; i++) {
int color = data[i] & 0xFF;
int mappedColor = rewriter.rewrite(color);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,34 +18,37 @@
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.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
public class SoundRewriter extends com.viaversion.viaversion.rewriter.SoundRewriter {
public class SoundRewriter<C extends ClientboundPacketType> extends com.viaversion.viaversion.rewriter.SoundRewriter<C> {
private final BackwardsProtocol protocol;
private final BackwardsProtocol<C, ?, ?, ?> protocol;
public SoundRewriter(BackwardsProtocol protocol) {
public SoundRewriter(final BackwardsProtocol<C, ?, ?, ?> protocol) {
super(protocol);
this.protocol = protocol;
}
public void registerNamedSound(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
public void registerNamedSound(final C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void registerMap() {
map(Type.STRING); // Sound identifier
public void register() {
map(Types.STRING); // Sound identifier
handler(getNamedSoundHandler());
}
});
}
public void registerStopSound(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
public void registerStopSound(final C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void registerMap() {
public void register() {
handler(getStopSoundHandler());
}
});
@@ -53,11 +56,14 @@ public class SoundRewriter extends com.viaversion.viaversion.rewriter.SoundRewri
public PacketHandler getNamedSoundHandler() {
return wrapper -> {
String soundId = wrapper.get(Type.STRING, 0);
String mappedId = protocol.getMappingData().getMappedNamedSound(soundId);
if (mappedId == null) return;
final String soundId = wrapper.get(Types.STRING, 0);
final String mappedId = protocol.getMappingData().getMappedNamedSound(soundId);
if (mappedId == null) {
return;
}
if (!mappedId.isEmpty()) {
wrapper.set(Type.STRING, 0, mappedId);
wrapper.set(Types.STRING, 0, mappedId);
} else {
wrapper.cancel();
}
@@ -66,27 +72,66 @@ public class SoundRewriter extends com.viaversion.viaversion.rewriter.SoundRewri
public PacketHandler getStopSoundHandler() {
return wrapper -> {
byte flags = wrapper.passthrough(Type.BYTE);
final byte flags = wrapper.passthrough(Types.BYTE);
if ((flags & 0x02) == 0) return; // No sound specified
if ((flags & 0x01) != 0) {
wrapper.passthrough(Type.VAR_INT); // Source
wrapper.passthrough(Types.VAR_INT); // Source
}
String soundId = wrapper.read(Type.STRING);
String mappedId = protocol.getMappingData().getMappedNamedSound(soundId);
final String soundId = wrapper.read(Types.STRING);
final String mappedId = protocol.getMappingData().getMappedNamedSound(soundId);
if (mappedId == null) {
// No mapping found
wrapper.write(Type.STRING, soundId);
wrapper.write(Types.STRING, soundId);
return;
}
if (!mappedId.isEmpty()) {
wrapper.write(Type.STRING, mappedId);
wrapper.write(Types.STRING, mappedId);
} else {
// 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() {
return wrapper -> {
Holder<SoundEvent> soundEventHolder = wrapper.read(Types.SOUND_EVENT);
if (soundEventHolder.isDirect()) {
wrapper.write(Types.SOUND_EVENT, rewriteSoundEvent(wrapper, soundEventHolder));
return;
}
final int mappedId = idRewriter.rewrite(soundEventHolder.id());
if (mappedId == -1) {
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;
}
}
@@ -0,0 +1,201 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2024 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.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viabackwards.api.data.BackwardsMappingData;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
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.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.libs.fastutil.ints.Int2IntMap;
import com.viaversion.viaversion.libs.fastutil.ints.IntIntPair;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectIterator;
import com.viaversion.viaversion.rewriter.IdRewriteFunction;
import com.viaversion.viaversion.util.ComponentUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StructuredEnchantmentRewriter {
protected final BackwardsStructuredItemRewriter<?, ?, ?> itemRewriter;
private boolean rewriteIds = true;
public StructuredEnchantmentRewriter(final BackwardsStructuredItemRewriter<?, ?, ?> itemRewriter) {
this.itemRewriter = itemRewriter;
}
public void handleToClient(final Item item) {
final StructuredDataContainer data = item.dataContainer();
final BackwardsMappingData mappingData = itemRewriter.protocol().getMappingData();
final IdRewriteFunction idRewriteFunction = id -> {
final Mappings mappings = mappingData.getEnchantmentMappings();
return mappings.getNewId(id);
};
final DescriptionSupplier descriptionSupplier = (id, level) -> {
final String remappedName = mappingData.mappedEnchantmentName(id);
return ComponentUtil.jsonStringToTag(ComponentUtil.legacyToJsonString("§7" + remappedName + " " + EnchantmentRewriter.getRomanNumber(level), true));
};
rewriteEnchantmentsToClient(data, StructuredDataKey.ENCHANTMENTS, idRewriteFunction, descriptionSupplier, false);
rewriteEnchantmentsToClient(data, StructuredDataKey.STORED_ENCHANTMENTS, idRewriteFunction, descriptionSupplier, true);
}
public void handleToServer(final Item item) {
final StructuredDataContainer data = item.dataContainer();
final StructuredData<CompoundTag> customData = data.getNonEmpty(StructuredDataKey.CUSTOM_DATA);
if (customData == null) {
return;
}
final CompoundTag tag = customData.value();
rewriteEnchantmentsToServer(data, tag, StructuredDataKey.ENCHANTMENTS);
rewriteEnchantmentsToServer(data, tag, StructuredDataKey.STORED_ENCHANTMENTS);
}
public void rewriteEnchantmentsToClient(final StructuredDataContainer data, final StructuredDataKey<Enchantments> key, final IdRewriteFunction rewriteFunction, final DescriptionSupplier descriptionSupplier, final boolean storedEnchant) {
final StructuredData<Enchantments> enchantmentsData = data.getNonEmpty(key);
if (enchantmentsData == null) {
return;
}
final CompoundTag tag = data.computeIfAbsent(StructuredDataKey.CUSTOM_DATA, $ -> new CompoundTag()).value();
final Enchantments enchantments = enchantmentsData.value();
final List<Tag> loreToAdd = new ArrayList<>();
boolean changed = false;
final ObjectIterator<Int2IntMap.Entry> iterator = enchantments.enchantments().int2IntEntrySet().iterator();
final List<IntIntPair> updatedIds = new ArrayList<>();
while (iterator.hasNext()) {
final Int2IntMap.Entry entry = iterator.next();
final int id = entry.getIntKey();
final int mappedId = rewriteFunction.rewrite(id);
if (mappedId != -1) {
if (rewriteIds) {
// Update the map after to iteration to preserve the current ids before possibly saving the original, avoid CME
updatedIds.add(IntIntPair.of(id, mappedId));
}
continue;
}
final int level = entry.getIntValue();
final Tag description = descriptionSupplier.get(id, level);
if (description != null) {
if (!changed) {
// Backup original before doing modifications
itemRewriter.saveListTag(tag, asTag(enchantments), key.identifier());
changed = true;
}
loreToAdd.add(description);
iterator.remove();
}
}
for (final IntIntPair pair : updatedIds) {
final int level = enchantments.enchantments().remove(pair.firstInt());
enchantments.add(pair.secondInt(), level);
}
if (loreToAdd.isEmpty()) {
// No removed enchantments
return;
}
// Add glint override if there are no enchantments left
if (!storedEnchant && enchantments.size() == 0) {
final StructuredData<Boolean> glintOverride = data.getNonEmpty(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE);
if (glintOverride != null) {
tag.putBoolean(itemRewriter.nbtTagName("glint"), glintOverride.value());
} else {
tag.putBoolean(itemRewriter.nbtTagName("noglint"), true);
}
data.set(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, true);
}
// Save original lore
final StructuredData<Tag[]> loreData = data.getNonEmpty(StructuredDataKey.LORE);
if (loreData != null) {
final List<Tag> loreList = Arrays.asList(loreData.value());
itemRewriter.saveGenericTagList(tag, loreList, "lore");
loreToAdd.addAll(loreList);
} else {
tag.putBoolean(itemRewriter.nbtTagName("nolore"), true);
}
if (enchantments.showInTooltip()) {
tag.putBoolean(itemRewriter.nbtTagName("show_" + key.identifier()), true);
}
data.set(StructuredDataKey.LORE, loreToAdd.toArray(new Tag[0]));
}
private ListTag<CompoundTag> asTag(final Enchantments enchantments) {
final ListTag<CompoundTag> listTag = new ListTag<>(CompoundTag.class);
for (final Int2IntMap.Entry entry : enchantments.enchantments().int2IntEntrySet()) {
final CompoundTag enchantment = new CompoundTag();
enchantment.putInt("id", entry.getIntKey());
enchantment.putInt("lvl", entry.getIntValue());
listTag.add(enchantment);
}
return listTag;
}
public void rewriteEnchantmentsToServer(final StructuredDataContainer data, final CompoundTag tag, final StructuredDataKey<Enchantments> key) {
final ListTag<CompoundTag> enchantmentsTag = itemRewriter.removeListTag(tag, key.identifier(), CompoundTag.class);
if (enchantmentsTag == null) {
return;
}
final Tag glintTag = tag.remove(itemRewriter.nbtTagName("glint"));
if (glintTag instanceof ByteTag) {
data.set(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, ((NumberTag) glintTag).asBoolean());
} else if (tag.remove(itemRewriter.nbtTagName("noglint")) != null) {
data.remove(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE);
}
final List<Tag> lore = itemRewriter.removeGenericTagList(tag, "lore");
if (lore != null) {
data.set(StructuredDataKey.LORE, lore.toArray(new Tag[0]));
} else if (tag.remove(itemRewriter.nbtTagName("nolore")) != null) {
data.remove(StructuredDataKey.LORE);
}
final Enchantments enchantments = new Enchantments(tag.remove(itemRewriter.nbtTagName("show_" + key.identifier())) != null);
for (final CompoundTag enchantment : enchantmentsTag) {
enchantments.add(enchantment.getInt("id"), enchantment.getInt("lvl"));
}
data.set(key, enchantments);
}
public void setRewriteIds(final boolean rewriteIds) {
this.rewriteIds = rewriteIds;
}
@FunctionalInterface
public interface DescriptionSupplier {
Tag get(int id, int level);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 ViaVersion and contributors
* Copyright (C) 2016-2024 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,128 +17,77 @@
*/
package com.viaversion.viabackwards.api.rewriters;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.VBMappingDataLoader;
import com.viaversion.viabackwards.api.data.BackwardsMappingDataLoader;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public class TranslatableRewriter extends ComponentRewriter {
public class TranslatableRewriter<C extends ClientboundPacketType> extends ComponentRewriter<C> {
private static final Map<String, Map<String, String>> TRANSLATABLES = new HashMap<>();
protected final Map<String, String> newTranslatables;
private final Map<String, String> translatables;
public static void loadTranslatables() {
JsonObject jsonObject = VBMappingDataLoader.loadData("translation-mappings.json");
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
Map<String, String> versionMappings = new HashMap<>();
TRANSLATABLES.put(entry.getKey(), versionMappings);
for (Map.Entry<String, JsonElement> translationEntry : entry.getValue().getAsJsonObject().entrySet()) {
if (!TRANSLATABLES.isEmpty()) {
throw new IllegalStateException("Translatables already loaded!");
}
fillTranslatables(BackwardsMappingDataLoader.INSTANCE.loadFromDataDir("translation-mappings.json"), TRANSLATABLES);
}
public static void fillTranslatables(final JsonObject jsonObject, final Map<String, Map<String, String>> translatables) {
for (final Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
final Map<String, String> versionMappings = new HashMap<>();
translatables.put(entry.getKey(), versionMappings);
for (final Map.Entry<String, JsonElement> translationEntry : entry.getValue().getAsJsonObject().entrySet()) {
versionMappings.put(translationEntry.getKey(), translationEntry.getValue().getAsString());
}
}
}
public TranslatableRewriter(BackwardsProtocol protocol) {
this(protocol, protocol.getClass().getSimpleName().split("To")[1].replace("_", "."));
public TranslatableRewriter(final BackwardsProtocol<C, ?, ?, ?> protocol, final ReadType type) {
this(protocol, type, protocol.getClass().getSimpleName().replace("Protocol", "").split("To")[0].replace("_", "."));
}
public TranslatableRewriter(BackwardsProtocol protocol, String sectionIdentifier) {
super(protocol);
final Map<String, String> newTranslatables = TRANSLATABLES.get(sectionIdentifier);
if (newTranslatables == null) {
ViaBackwards.getPlatform().getLogger().warning("Error loading " + sectionIdentifier + " translatables!");
this.newTranslatables = new HashMap<>();
public TranslatableRewriter(final BackwardsProtocol<C, ?, ?, ?> protocol, final ReadType type, final String version) {
super(protocol, type);
final Map<String, String> translatableMappings = getTranslatableMappings(version);
if (translatableMappings == null) {
protocol.getLogger().warning("Missing " + version + " translatables!");
this.translatables = new HashMap<>();
} else {
this.newTranslatables = newTranslatables;
this.translatables = translatableMappings;
}
}
public void registerPing() {
protocol.registerClientbound(State.LOGIN, 0x00, 0x00, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
public void registerDisconnect(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
public void registerChatMessage(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
public void registerLegacyOpenWindow(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // Id
map(Type.STRING); // Window Type
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
public void registerOpenWindow(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Id
map(Type.VAR_INT); // Window Type
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
public void registerTabList(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
processText(wrapper.passthrough(Type.COMPONENT));
processText(wrapper.passthrough(Type.COMPONENT));
});
}
});
}
public void registerCombatKill(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.INT);
handler(wrapper -> processText(wrapper.passthrough(Type.COMPONENT)));
}
});
}
@Override
protected void handleTranslate(JsonObject root, String translate) {
String newTranslate = newTranslatables.get(translate);
protected void handleTranslate(final JsonObject root, final String translate) {
final String newTranslate = mappedTranslationKey(translate);
if (newTranslate != null) {
root.addProperty("translate", newTranslate);
}
}
@Override
protected void handleTranslate(final UserConnection connection, final CompoundTag parentTag, final StringTag translateTag) {
final String newTranslate = mappedTranslationKey(translateTag.getValue());
if (newTranslate != null) {
parentTag.put("translate", new StringTag(newTranslate));
}
}
public @Nullable String mappedTranslationKey(final String translationKey) {
return translatables.get(translationKey);
}
public Map<String, String> getTranslatableMappings(final String sectionIdentifier) {
return TRANSLATABLES.get(sectionIdentifier);
}
}
@@ -1,89 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_10to1_11;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.packets.BlockItemPackets1_11;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.packets.EntityPackets1_11;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.packets.PlayerPackets1_11;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.storage.WindowTracker;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_11Types;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class Protocol1_10To1_11 extends BackwardsProtocol<ClientboundPackets1_9_3, ClientboundPackets1_9_3, ServerboundPackets1_9_3, ServerboundPackets1_9_3> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.11", "1.10", null, true);
private final EntityPackets1_11 entityPackets = new EntityPackets1_11(this); // Required for the item rewriter
private BlockItemPackets1_11 blockItemPackets;
public Protocol1_10To1_11() {
super(ClientboundPackets1_9_3.class, ClientboundPackets1_9_3.class, ServerboundPackets1_9_3.class, ServerboundPackets1_9_3.class);
}
@Override
protected void registerPackets() {
(blockItemPackets = new BlockItemPackets1_11(this)).register();
entityPackets.register();
new PlayerPackets1_11().register(this);
SoundRewriter soundRewriter = new SoundRewriter(this);
soundRewriter.registerNamedSound(ClientboundPackets1_9_3.NAMED_SOUND);
soundRewriter.registerSound(ClientboundPackets1_9_3.SOUND);
}
@Override
public void init(UserConnection user) {
// Register ClientWorld
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld(user));
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_11Types.EntityType.PLAYER, true));
if (!user.has(WindowTracker.class)) {
user.put(new WindowTracker());
}
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityPackets1_11 getEntityRewriter() {
return entityPackets;
}
@Override
public BlockItemPackets1_11 getItemRewriter() {
return blockItemPackets;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -1,458 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_10to1_11.packets;
import com.viaversion.viabackwards.api.data.MappedLegacyBlockItem;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.storage.ChestedHorseStorage;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.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.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_11Types;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_11to1_10.EntityIdRewriter;
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import java.util.Arrays;
import java.util.Optional;
public class BlockItemPackets1_11 extends LegacyBlockItemRewriter<Protocol1_10To1_11> {
private LegacyEnchantmentRewriter enchantmentRewriter;
public BlockItemPackets1_11(Protocol1_10To1_11 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_9_3.SET_SLOT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot ID
map(Type.ITEM); // 2 - Slot Value
handler(itemToClientHandler(Type.ITEM));
// Handle Llama
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (isLlama(wrapper.user())) {
Optional<ChestedHorseStorage> horse = getChestedHorse(wrapper.user());
if (!horse.isPresent())
return;
ChestedHorseStorage storage = horse.get();
int currentSlot = wrapper.get(Type.SHORT, 0);
wrapper.set(Type.SHORT, 0, ((Integer) (currentSlot = getNewSlotId(storage, currentSlot))).shortValue());
wrapper.set(Type.ITEM, 0, getNewItem(storage, currentSlot, wrapper.get(Type.ITEM, 0)));
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.WINDOW_ITEMS, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.ITEM_ARRAY); // 1 - Window Values
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Item[] stacks = wrapper.get(Type.ITEM_ARRAY, 0);
for (int i = 0; i < stacks.length; i++)
stacks[i] = handleItemToClient(stacks[i]);
if (isLlama(wrapper.user())) {
Optional<ChestedHorseStorage> horse = getChestedHorse(wrapper.user());
if (!horse.isPresent())
return;
ChestedHorseStorage storage = horse.get();
stacks = Arrays.copyOf(stacks, !storage.isChested() ? 38 : 53);
for (int i = stacks.length - 1; i >= 0; i--) {
stacks[getNewSlotId(storage, i)] = stacks[i];
stacks[i] = getNewItem(storage, i, stacks[i]);
}
wrapper.set(Type.ITEM_ARRAY, 0, stacks);
}
}
});
}
});
registerEntityEquipment(ClientboundPackets1_9_3.ENTITY_EQUIPMENT, Type.ITEM);
// Plugin message Packet -> Trading
protocol.registerClientbound(ClientboundPackets1_9_3.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // 0 - Channel
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (wrapper.get(Type.STRING, 0).equalsIgnoreCase("MC|TrList")) {
wrapper.passthrough(Type.INT); // Passthrough Window ID
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Input Item
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Output Item
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item
if (secondItem) {
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Second Item
}
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
}
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_9_3.CLICK_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot
map(Type.BYTE); // 2 - Button
map(Type.SHORT); // 3 - Action number
map(Type.VAR_INT); // 4 - Mode
map(Type.ITEM); // 5 - Clicked Item
handler(itemToServerHandler(Type.ITEM));
// Llama slot
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (isLlama(wrapper.user())) {
Optional<ChestedHorseStorage> horse = getChestedHorse(wrapper.user());
if (!horse.isPresent())
return;
ChestedHorseStorage storage = horse.get();
int clickSlot = wrapper.get(Type.SHORT, 0);
int correctSlot = getOldSlotId(storage, clickSlot);
wrapper.set(Type.SHORT, 0, ((Integer) correctSlot).shortValue());
}
}
});
}
});
registerCreativeInvAction(ServerboundPackets1_9_3.CREATIVE_INVENTORY_ACTION, Type.ITEM);
protocol.registerClientbound(ClientboundPackets1_9_3.CHUNK_DATA, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
Chunk1_9_3_4Type type = new Chunk1_9_3_4Type(clientWorld); // Use the 1.10 Chunk type since nothing changed.
Chunk chunk = wrapper.passthrough(type);
handleChunk(chunk);
// only patch it for signs for now
for (CompoundTag tag : chunk.getBlockEntities()) {
Tag idTag = tag.get("id");
if (!(idTag instanceof StringTag)) continue;
String id = (String) idTag.getValue();
if (id.equals("minecraft:sign")) {
((StringTag) idTag).setValue("Sign");
}
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.BLOCK_CHANGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Block Position
map(Type.VAR_INT); // 1 - Block
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int idx = wrapper.get(Type.VAR_INT, 0);
wrapper.set(Type.VAR_INT, 0, handleBlockID(idx));
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.MULTI_BLOCK_CHANGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Chunk X
map(Type.INT); // 1 - Chunk Z
map(Type.BLOCK_CHANGE_RECORD_ARRAY);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (BlockChangeRecord record : wrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0)) {
record.setBlockId(handleBlockID(record.getBlockId()));
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.BLOCK_ENTITY_DATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Position
map(Type.UNSIGNED_BYTE); // 1 - Action
map(Type.NBT); // 2 - NBT
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Remove on shulkerbox decleration
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 10) {
wrapper.cancel();
}
// Handler Spawners
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 1) {
CompoundTag tag = wrapper.get(Type.NBT, 0);
EntityIdRewriter.toClientSpawner(tag, true);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.OPEN_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.STRING); // 1 - Window Type
map(Type.COMPONENT); // 2 - Title
map(Type.UNSIGNED_BYTE); // 3 - Slots
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int entityId = -1;
// Passthrough Entity ID
if (wrapper.get(Type.STRING, 0).equals("EntityHorse")) {
entityId = wrapper.passthrough(Type.INT);
}
// Track Inventory
String inventory = wrapper.get(Type.STRING, 0);
WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
windowTracker.setInventory(inventory);
windowTracker.setEntityId(entityId);
// Change llama slotcount to the donkey one
if (isLlama(wrapper.user())) {
wrapper.set(Type.UNSIGNED_BYTE, 1, (short) 17);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.CLOSE_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
// Inventory tracking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
windowTracker.setInventory(null);
windowTracker.setEntityId(-1);
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_9_3.CLOSE_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
// Inventory tracking
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
WindowTracker windowTracker = wrapper.user().get(WindowTracker.class);
windowTracker.setInventory(null);
windowTracker.setEntityId(-1);
}
});
}
});
protocol.getEntityRewriter().filter().handler((event, meta) -> {
if (meta.metaType().type().equals(Type.ITEM)) // Is Item
meta.setValue(handleItemToClient((Item) meta.getValue()));
});
}
@Override
protected void registerRewrites() {
// Handle spawner block entity (map to itself with custom handler)
MappedLegacyBlockItem data = replacementData.computeIfAbsent(52, s -> new MappedLegacyBlockItem(52, (short) -1, null, false));
data.setBlockEntityHandler((b, tag) -> {
EntityIdRewriter.toClientSpawner(tag, true);
return tag;
});
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName);
enchantmentRewriter.registerEnchantment(71, "§cCurse of Vanishing");
enchantmentRewriter.registerEnchantment(10, "§cCurse of Binding");
enchantmentRewriter.setHideLevelForEnchants(71, 10); // Curses do not display their level
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
super.handleItemToClient(item);
CompoundTag tag = item.tag();
if (tag == null) return item;
// Rewrite spawn eggs (id checks are done in the method itself)
EntityIdRewriter.toClientItem(item, true);
if (tag.get("ench") instanceof ListTag) {
enchantmentRewriter.rewriteEnchantmentsToClient(tag, false);
}
if (tag.get("StoredEnchantments") instanceof ListTag) {
enchantmentRewriter.rewriteEnchantmentsToClient(tag, true);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
super.handleItemToServer(item);
CompoundTag tag = item.tag();
if (tag == null) return item;
// Rewrite spawn eggs (id checks are done in the method itself)
EntityIdRewriter.toServerItem(item, true);
if (tag.contains(nbtTagName + "|ench")) {
enchantmentRewriter.rewriteEnchantmentsToServer(tag, false);
}
if (tag.contains(nbtTagName + "|StoredEnchantments")) {
enchantmentRewriter.rewriteEnchantmentsToServer(tag, true);
}
return item;
}
private boolean isLlama(UserConnection user) {
WindowTracker tracker = user.get(WindowTracker.class);
if (tracker.getInventory() != null && tracker.getInventory().equals("EntityHorse")) {
EntityTracker entTracker = user.getEntityTracker(Protocol1_10To1_11.class);
StoredEntityData entityData = entTracker.entityData(tracker.getEntityId());
return entityData != null && entityData.type().is(Entity1_11Types.EntityType.LIAMA);
}
return false;
}
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_10To1_11.class);
StoredEntityData entityData = entTracker.entityData(tracker.getEntityId());
if (entityData != null)
return Optional.of(entityData.get(ChestedHorseStorage.class));
}
return Optional.empty();
}
private int getNewSlotId(ChestedHorseStorage storage, int slotId) {
int totalSlots = !storage.isChested() ? 38 : 53;
int strength = storage.isChested() ? storage.getLiamaStrength() : 0;
int startNonExistingFormula = 2 + 3 * strength;
int offsetForm = 15 - (3 * strength);
if (slotId >= startNonExistingFormula && totalSlots > (slotId + offsetForm))
return offsetForm + slotId;
if (slotId == 1)
return 0;
return slotId;
}
private int getOldSlotId(ChestedHorseStorage storage, int slotId) {
int strength = storage.isChested() ? storage.getLiamaStrength() : 0;
int startNonExistingFormula = 2 + 3 * strength;
int endNonExistingFormula = 2 + 3 * (storage.isChested() ? 5 : 0);
int offsetForm = endNonExistingFormula - startNonExistingFormula;
if (slotId == 1 || slotId >= startNonExistingFormula && slotId < endNonExistingFormula)
return 0;
if (slotId >= endNonExistingFormula)
return slotId - offsetForm;
if (slotId == 0)
return 1;
return slotId;
}
private Item getNewItem(ChestedHorseStorage storage, int slotId, Item current) {
int strength = storage.isChested() ? storage.getLiamaStrength() : 0;
int startNonExistingFormula = 2 + 3 * strength;
int endNonExistingFormula = 2 + 3 * (storage.isChested() ? 5 : 0);
if (slotId >= startNonExistingFormula && slotId < endNonExistingFormula)
return new DataItem(166, (byte) 1, (short) 0, getNamedTag("§4SLOT DISABLED"));
if (slotId == 1)
return null;
return current;
}
}
@@ -1,412 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_10to1_11.packets;
import com.viaversion.viabackwards.api.entities.storage.EntityData;
import com.viaversion.viabackwards.api.entities.storage.WrappedMetadata;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.PotionSplashHandler;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.storage.ChestedHorseStorage;
import com.viaversion.viabackwards.utils.Block;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_11Types;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_12Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_9;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import java.util.List;
import java.util.Optional;
public class EntityPackets1_11 extends LegacyEntityRewriter<Protocol1_10To1_11> {
public EntityPackets1_11(Protocol1_10To1_11 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_9_3.EFFECT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT);
map(Type.POSITION);
map(Type.INT);
handler(wrapper -> {
int type = wrapper.get(Type.INT, 0);
if (type == 2002 || type == 2007) {
// 2007 potion id doesn't exist in 1.10
if (type == 2007) {
wrapper.set(Type.INT, 0, 2002);
}
int mappedData = PotionSplashHandler.getOldData(wrapper.get(Type.INT, 1));
if (mappedData != -1) {
wrapper.set(Type.INT, 1, mappedData);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.SPAWN_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - x
map(Type.DOUBLE); // 4 - y
map(Type.DOUBLE); // 5 - z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - data
// Track Entity
handler(getObjectTrackerHandler());
handler(getObjectRewriter(id -> Entity1_11Types.ObjectType.findById(id).orElse(null)));
// Handle FallingBlock blocks
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<Entity1_12Types.ObjectType> type = Entity1_12Types.ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent() && type.get() == Entity1_12Types.ObjectType.FALLING_BLOCK) {
int objectData = wrapper.get(Type.INT, 0);
int objType = objectData & 4095;
int data = objectData >> 12 & 15;
Block block = protocol.getItemRewriter().handleBlock(objType, data);
if (block == null)
return;
wrapper.set(Type.INT, 0, block.getId() | block.getData() << 12);
}
}
});
}
});
registerTracker(ClientboundPackets1_9_3.SPAWN_EXPERIENCE_ORB, Entity1_11Types.EntityType.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_9_3.SPAWN_GLOBAL_ENTITY, Entity1_11Types.EntityType.WEATHER);
protocol.registerClientbound(ClientboundPackets1_9_3.SPAWN_MOB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.VAR_INT, Type.UNSIGNED_BYTE); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Yaw
map(Type.BYTE); // 7 - Pitch
map(Type.BYTE); // 8 - Head Pitch
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
map(Types1_9.METADATA_LIST); // 12 - Metadata
// Track entity
handler(getTrackerHandler(Type.UNSIGNED_BYTE, 0));
// Rewrite entity type / metadata
handler(wrapper -> {
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityType type = tracker(wrapper.user()).entityType(entityId);
List<Metadata> list = wrapper.get(Types1_9.METADATA_LIST, 0);
handleMetadata(wrapper.get(Type.VAR_INT, 0), list, wrapper.user());
EntityData entityData = entityDataForType(type);
if (entityData != null) {
wrapper.set(Type.UNSIGNED_BYTE, 0, (short) entityData.replacementId());
if (entityData.hasBaseMeta()) {
entityData.defaultMeta().createMeta(new WrappedMetadata(list));
}
}
// Sub 1.11 clients will error if the list is empty
if (list.isEmpty()) {
list.add(new Metadata(0, MetaType1_9.Byte, (byte) 0));
}
});
}
});
registerTracker(ClientboundPackets1_9_3.SPAWN_PAINTING, Entity1_11Types.EntityType.PAINTING);
registerJoinGame(ClientboundPackets1_9_3.JOIN_GAME, Entity1_11Types.EntityType.PLAYER);
registerRespawn(ClientboundPackets1_9_3.RESPAWN);
protocol.registerClientbound(ClientboundPackets1_9_3.SPAWN_PLAYER, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Player UUID
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Types1_9.METADATA_LIST); // 7 - Metadata list
handler(getTrackerAndMetaHandler(Types1_9.METADATA_LIST, Entity1_11Types.EntityType.PLAYER));
handler(wrapper -> {
// Sub 1.11 clients will cry if the list is empty
List<Metadata> metadata = wrapper.get(Types1_9.METADATA_LIST, 0);
if (metadata.isEmpty()) {
metadata.add(new Metadata(0, MetaType1_9.Byte, (byte) 0));
}
});
}
});
registerRemoveEntities(ClientboundPackets1_9_3.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_9_3.ENTITY_METADATA, Types1_9.METADATA_LIST);
protocol.registerClientbound(ClientboundPackets1_9_3.ENTITY_STATUS, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Entity ID
map(Type.BYTE); // 1 - Entity Status
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
byte b = wrapper.get(Type.BYTE, 0);
if (b == 35) {
wrapper.clearPacket();
wrapper.setId(0x1E); // Change Game State
wrapper.write(Type.UNSIGNED_BYTE, (short) 10); // Play Elder Guardian animation
wrapper.write(Type.FLOAT, 0F);
}
}
});
}
});
}
@Override
protected void registerRewrites() {
// Guardian
mapEntityTypeWithData(Entity1_11Types.EntityType.ELDER_GUARDIAN, Entity1_11Types.EntityType.GUARDIAN);
// Skeletons
mapEntityTypeWithData(Entity1_11Types.EntityType.WITHER_SKELETON, Entity1_11Types.EntityType.SKELETON).plainName().spawnMetadata(storage -> storage.add(getSkeletonTypeMeta(1)));
mapEntityTypeWithData(Entity1_11Types.EntityType.STRAY, Entity1_11Types.EntityType.SKELETON).plainName().spawnMetadata(storage -> storage.add(getSkeletonTypeMeta(2)));
// Zombies
mapEntityTypeWithData(Entity1_11Types.EntityType.HUSK, Entity1_11Types.EntityType.ZOMBIE).plainName().spawnMetadata(storage -> handleZombieType(storage, 6));
mapEntityTypeWithData(Entity1_11Types.EntityType.ZOMBIE_VILLAGER, Entity1_11Types.EntityType.ZOMBIE).spawnMetadata(storage -> handleZombieType(storage, 1));
// Horses
mapEntityTypeWithData(Entity1_11Types.EntityType.HORSE, Entity1_11Types.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(0))); // Nob able to ride the horse without having the MetaType sent.
mapEntityTypeWithData(Entity1_11Types.EntityType.DONKEY, Entity1_11Types.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(1)));
mapEntityTypeWithData(Entity1_11Types.EntityType.MULE, Entity1_11Types.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(2)));
mapEntityTypeWithData(Entity1_11Types.EntityType.SKELETON_HORSE, Entity1_11Types.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(4)));
mapEntityTypeWithData(Entity1_11Types.EntityType.ZOMBIE_HORSE, Entity1_11Types.EntityType.HORSE).spawnMetadata(storage -> storage.add(getHorseMetaType(3)));
// New mobs
mapEntityTypeWithData(Entity1_11Types.EntityType.EVOCATION_FANGS, Entity1_11Types.EntityType.SHULKER);
mapEntityTypeWithData(Entity1_11Types.EntityType.EVOCATION_ILLAGER, Entity1_11Types.EntityType.VILLAGER).plainName();
mapEntityTypeWithData(Entity1_11Types.EntityType.VEX, Entity1_11Types.EntityType.BAT).plainName();
mapEntityTypeWithData(Entity1_11Types.EntityType.VINDICATION_ILLAGER, Entity1_11Types.EntityType.VILLAGER).plainName().spawnMetadata(storage -> storage.add(new Metadata(13, MetaType1_9.VarInt, 4))); // Base Profession
mapEntityTypeWithData(Entity1_11Types.EntityType.LIAMA, Entity1_11Types.EntityType.HORSE).plainName().spawnMetadata(storage -> storage.add(getHorseMetaType(1)));
mapEntityTypeWithData(Entity1_11Types.EntityType.LIAMA_SPIT, Entity1_11Types.EntityType.SNOWBALL);
mapObjectType(Entity1_11Types.ObjectType.LIAMA_SPIT, Entity1_11Types.ObjectType.SNOWBALL, -1);
// Replace with endertorchthingies
mapObjectType(Entity1_11Types.ObjectType.EVOCATION_FANGS, Entity1_11Types.ObjectType.FALLING_BLOCK, 198 | 1 << 12);
// Handle ElderGuardian & target metadata
filter().filterFamily(Entity1_11Types.EntityType.GUARDIAN).index(12).handler((event, meta) -> {
boolean b = (boolean) meta.getValue();
int bitmask = b ? 0x02 : 0;
if (event.entityType() == Entity1_11Types.EntityType.ELDER_GUARDIAN) {
bitmask |= 0x04;
}
meta.setTypeAndValue(MetaType1_9.Byte, (byte) bitmask);
});
// Handle skeleton swing
filter().filterFamily(Entity1_11Types.EntityType.ABSTRACT_SKELETON).index(12).toIndex(13);
/*
ZOMBIE CHANGES
*/
filter().filterFamily(Entity1_11Types.EntityType.ZOMBIE).handler((event, meta) -> {
switch (meta.id()) {
case 13:
event.cancel();
return;
case 14:
event.setIndex(15);
break;
case 15:
event.setIndex(14);
break;
// Profession
case 16:
event.setIndex(13);
meta.setValue(1 + (int) meta.getValue());
break;
}
});
// Handle Evocation Illager
filter().type(Entity1_11Types.EntityType.EVOCATION_ILLAGER).index(12).handler((event, meta) -> {
event.setIndex(13);
meta.setTypeAndValue(MetaType1_9.VarInt, ((Byte) meta.getValue()).intValue()); // Change the profession for the states
});
// Handle Vex (Remove this field completely since the position is not updated correctly when idling for bats. Sad ):
filter().type(Entity1_11Types.EntityType.VEX).index(12).handler((event, meta) -> {
meta.setValue((byte) 0x00);
});
// Handle VindicationIllager
filter().type(Entity1_11Types.EntityType.VINDICATION_ILLAGER).index(12).handler((event, meta) -> {
event.setIndex(13);
meta.setTypeAndValue(MetaType1_9.VarInt, ((Number) meta.getValue()).intValue() == 1 ? 2 : 4);
});
/*
HORSES
*/
// Handle horse flags
filter().filterFamily(Entity1_11Types.EntityType.ABSTRACT_HORSE).index(13).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
byte b = (byte) meta.getValue();
if (data.has(ChestedHorseStorage.class) && data.get(ChestedHorseStorage.class).isChested()) {
b |= 0x08; // Chested
meta.setValue(b);
}
});
// Create chested horse storage
filter().filterFamily(Entity1_11Types.EntityType.CHESTED_HORSE).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
if (!data.has(ChestedHorseStorage.class)) {
data.put(new ChestedHorseStorage());
}
});
// Handle horse armor
filter().type(Entity1_11Types.EntityType.HORSE).index(16).toIndex(17);
// Handle chested horse
filter().filterFamily(Entity1_11Types.EntityType.CHESTED_HORSE).index(15).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
ChestedHorseStorage storage = data.get(ChestedHorseStorage.class);
boolean b = (boolean) meta.getValue();
storage.setChested(b);
event.cancel();
});
// Get rid of Liama metadata
filter().type(Entity1_11Types.EntityType.LIAMA).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
ChestedHorseStorage storage = data.get(ChestedHorseStorage.class);
int index = event.index();
// Store them for later (:
switch (index) {
case 16:
storage.setLiamaStrength((int) meta.getValue());
event.cancel();
break;
case 17:
storage.setLiamaCarpetColor((int) meta.getValue());
event.cancel();
break;
case 18:
storage.setLiamaVariant((int) meta.getValue());
event.cancel();
break;
}
});
// Handle Horse (Correct owner)
filter().filterFamily(Entity1_11Types.EntityType.ABSTRACT_HORSE).index(14).toIndex(16);
// Handle villager - Change non-existing profession
filter().type(Entity1_11Types.EntityType.VILLAGER).index(13).handler((event, meta) -> {
if ((int) meta.getValue() == 5) {
meta.setValue(0);
}
});
// handle new Shulker color meta
filter().type(Entity1_11Types.EntityType.SHULKER).cancel(15);
}
/*
0 - Skeleton
1 - Wither Skeleton
2 - Stray
*/
private Metadata getSkeletonTypeMeta(int type) {
return new Metadata(12, MetaType1_9.VarInt, type);
}
/*
0 - Zombie
1-5 - Villager with profession
6 - Husk
*/
private Metadata getZombieTypeMeta(int type) {
return new Metadata(13, MetaType1_9.VarInt, type);
}
private void handleZombieType(WrappedMetadata storage, int type) {
Metadata meta = storage.get(13);
if (meta == null) {
storage.add(getZombieTypeMeta(type));
}
}
/*
Horse 0
Donkey 1
Mule 2
Zombie horse 3
Skeleton horse 4
*/
private Metadata getHorseMetaType(int type) {
return new Metadata(14, MetaType1_9.VarInt, type);
}
@Override
public EntityType typeFromId(int typeId) {
return Entity1_11Types.getTypeFromId(typeId, false);
}
@Override
protected EntityType getObjectTypeFromId(int typeId) {
return Entity1_11Types.getTypeFromId(typeId, true);
}
}
@@ -1,94 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_10to1_11.packets;
import com.viaversion.viabackwards.protocol.protocol1_10to1_11.Protocol1_10To1_11;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import com.viaversion.viaversion.libs.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
public class PlayerPackets1_11 {
private static final ValueTransformer<Short, Float> TO_NEW_FLOAT = new ValueTransformer<Short, Float>(Type.FLOAT) {
@Override
public Float transform(PacketWrapper wrapper, Short inputValue) throws Exception {
return inputValue / 15f;
}
};
public void register(Protocol1_10To1_11 protocol) {
protocol.registerClientbound(ClientboundPackets1_9_3.TITLE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Action
handler(wrapper -> {
int action = wrapper.get(Type.VAR_INT, 0);
if (action == 2) { // Handle the new ActionBar
JsonElement message = wrapper.read(Type.COMPONENT);
wrapper.clearPacket();
wrapper.setId(ClientboundPackets1_9_3.CHAT_MESSAGE.ordinal());
// https://bugs.mojang.com/browse/MC-119145to
String legacy = LegacyComponentSerializer.legacySection().serialize(GsonComponentSerializer.gson().deserialize(message.toString()));
message = new JsonObject();
message.getAsJsonObject().addProperty("text", legacy);
wrapper.write(Type.COMPONENT, message);
wrapper.write(Type.BYTE, (byte) 2);
} else if (action > 2) {
wrapper.set(Type.VAR_INT, 0, action - 1); // Move everything one position down
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_9_3.COLLECT_ITEM, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Collected entity id
map(Type.VAR_INT); // 1 - Collector entity id
handler(wrapper -> wrapper.read(Type.VAR_INT)); // Ignore item pickup count
}
});
protocol.registerServerbound(ServerboundPackets1_9_3.PLAYER_BLOCK_PLACEMENT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Location
map(Type.VAR_INT); // 1 - Face
map(Type.VAR_INT); // 2 - Hand
map(Type.UNSIGNED_BYTE, TO_NEW_FLOAT);
map(Type.UNSIGNED_BYTE, TO_NEW_FLOAT);
map(Type.UNSIGNED_BYTE, TO_NEW_FLOAT);
}
});
}
}
@@ -1,112 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11_1to1_12;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.data.ShoulderTracker;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.packets.BlockItemPackets1_12;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.packets.ChatPackets1_12;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.packets.EntityPackets1_12;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.packets.SoundPackets1_12;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_12Types;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ClientboundPackets1_12;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ServerboundPackets1_12;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.Protocol1_9To1_8;
public class Protocol1_11_1To1_12 extends BackwardsProtocol<ClientboundPackets1_12, ClientboundPackets1_9_3, ServerboundPackets1_12, ServerboundPackets1_9_3> {
private static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.12", "1.11", null, true) {
@Override
protected boolean shouldWarnOnMissing(final String key) {
return super.shouldWarnOnMissing(key) && !key.equals("sounds");
}
};
private final EntityPackets1_12 entityPackets = new EntityPackets1_12(this);
private final BlockItemPackets1_12 blockItemPackets = new BlockItemPackets1_12(this);
public Protocol1_11_1To1_12() {
super(ClientboundPackets1_12.class, ClientboundPackets1_9_3.class, ServerboundPackets1_12.class, ServerboundPackets1_9_3.class);
}
@Override
protected void registerPackets() {
blockItemPackets.register();
entityPackets.register();
new SoundPackets1_12(this).register();
new ChatPackets1_12(this).register();
registerClientbound(ClientboundPackets1_12.TITLE, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
int action = wrapper.passthrough(Type.VAR_INT);
if (action >= 0 && action <= 2) {
JsonElement component = wrapper.read(Type.COMPONENT);
wrapper.write(Type.COMPONENT, Protocol1_9To1_8.fixJson(component.toString()));
}
});
}
});
cancelClientbound(ClientboundPackets1_12.ADVANCEMENTS);
cancelClientbound(ClientboundPackets1_12.UNLOCK_RECIPES);
cancelClientbound(ClientboundPackets1_12.SELECT_ADVANCEMENTS_TAB);
}
@Override
public void init(UserConnection user) {
// Register ClientWorld
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld(user));
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_12Types.EntityType.PLAYER, true));
user.put(new ShoulderTracker(user));
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityPackets1_12 getEntityRewriter() {
return entityPackets;
}
@Override
public BlockItemPackets1_12 getItemRewriter() {
return blockItemPackets;
}
@Override
public boolean hasMappingDataToLoad() {
return true;
}
}
@@ -1,154 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11_1to1_12.data;
import java.util.HashMap;
import java.util.Map;
public class AdvancementTranslations {
private static final Map<String, String> advancements = new HashMap<>();
static {
add("advancements.nether.get_wither_skull.title", "Spooky Scary Skeleton");
add("advancements.husbandry.break_diamond_hoe.description", "Completely use up a diamond hoe, and then reevaluate your life choices");
add("advancements.nether.fast_travel.description", "Use the Nether to travel 7km in the Overworld");
add("advancements.story.enter_the_end.description", "Enter the End Portal");
add("advancements.story.follow_ender_eye.title", "Eye Spy");
add("advancements.toast.task", "Advancement Made!");
add("advancements.nether.find_fortress.description", "Break your way into a Nether Fortress");
add("advancements.story.form_obsidian.description", "Form and mine a block of Obsidian");
add("advancements.adventure.sniper_duel.description", "Kill a skeleton with an arrow from more than 50 meters");
add("advancements.end.root.description", "Or the beginning?");
add("advancements.adventure.kill_a_mob.title", "Monster Hunter");
add("advancements.end.elytra.description", "Find an Elytra");
add("advancements.end.dragon_breath.description", "Collect dragon's breath in a glass bottle");
add("advancements.story.enter_the_nether.title", "We Need to Go Deeper");
add("advancements.story.upgrade_tools.title", "Getting an Upgrade");
add("advancements.story.lava_bucket.title", "Hot Stuff");
add("advancements.story.shiny_gear.title", "Cover Me With Diamonds");
add("advancements.story.smelt_iron.description", "Smelt an iron ingot");
add("chat.type.advancement.goal", "%s has reached the goal %s");
add("advancements.husbandry.break_diamond_hoe.title", "Serious Dedication");
add("advancements.story.iron_tools.description", "Upgrade your pickaxe");
add("advancements.end.respawn_dragon.title", "The End... Again...");
add("advancements.husbandry.tame_an_animal.description", "Tame an animal");
add("advancements.end.levitate.description", "Levitate up 50 blocks from the attacks of a Shulker");
add("advancements.adventure.shoot_arrow.description", "Shoot something with a bow and arrow");
add("advancements.nether.root.description", "Bring summer clothes");
add("advancements.story.enchant_item.description", "Enchant an item at an Enchanting Table");
add("advancements.adventure.root.title", "Adventure");
add("advancements.adventure.trade.title", "What a Deal!");
add("advancements.husbandry.breed_all_animals.title", "Two by Two");
add("advancements.nether.find_fortress.title", "A Terrible Fortress");
add("advancements.nether.create_full_beacon.title", "Beaconator");
add("advancements.story.cure_zombie_villager.description", "Weaken and then cure a zombie villager");
add("advancements.toast.challenge", "Challenge Complete!");
add("advancements.nether.create_full_beacon.description", "Bring a beacon to full power");
add("advancements.story.follow_ender_eye.description", "Follow an Ender Eye");
add("advancements.end.find_end_city.title", "The City at the End of the Game");
add("chat.type.advancement.challenge", "%s has completed the challenge %s");
add("advancements.story.deflect_arrow.title", "Not Today, Thank You");
add("advancements.adventure.kill_all_mobs.description", "Kill one of every hostile monster");
add("advancements.story.smelt_iron.title", "Acquire Hardware");
add("advancements.end.levitate.title", "Great View From Up Here");
add("advancements.end.kill_dragon.title", "Free the End");
add("advancements.end.kill_dragon.description", "Good luck");
add("advancements.nether.brew_potion.title", "Local Brewery");
add("advancements.story.enchant_item.title", "Enchanter");
add("advancements.end.respawn_dragon.description", "Respawn the ender dragon");
add("advancements.nether.uneasy_alliance.title", "Uneasy Alliance");
add("advancements.nether.root.title", "Nether");
add("advancements.nether.brew_potion.description", "Brew a potion");
add("advancements.nether.obtain_blaze_rod.title", "Into Fire");
add("advancements.nether.summon_wither.title", "Withering Heights");
add("advancements.story.root.title", "Minecraft");
add("advancements.husbandry.balanced_diet.description", "Eat everything that is edible, even if it's not good for you");
add("advancements.nether.uneasy_alliance.description", "Rescue a Ghast from the Nether, bring it safely home to the Overworld... and then kill it.");
add("advancements.husbandry.breed_all_animals.description", "Breed all the animals!");
add("advancements.adventure.kill_all_mobs.title", "Monsters Hunted");
add("advancements.story.cure_zombie_villager.title", "Zombie Doctor");
add("advancements.husbandry.plant_seed.title", "A Seedy Place");
add("advancements.end.dragon_breath.title", "You Need a Mint");
add("advancements.story.mine_stone.title", "Stone Age");
add("advancements.end.find_end_city.description", "Go on in, what could happen?");
add("advancements.nether.create_beacon.description", "Construct and place a Beacon");
add("advancements.adventure.summon_iron_golem.title", "Hired Help");
add("advancements.end.elytra.title", "Sky's the Limit");
add("chat.type.advancement.task", "%s has made the advancement %s");
add("advancements.story.deflect_arrow.description", "Deflect an arrow with a shield");
add("advancements.nether.all_effects.description", "Have every effect applied at the same time");
add("advancements.story.enter_the_nether.description", "Build, light and enter a Nether Portal");
add("advancements.story.mine_diamond.title", "Diamonds!");
add("advancements.husbandry.balanced_diet.title", "A Balanced Diet");
add("advancements.husbandry.root.title", "Husbandry");
add("advancements.story.root.description", "The heart and story of the game");
add("advancements.story.upgrade_tools.description", "Construct a better pickaxe");
add("advancements.nether.all_effects.title", "How Did We Get Here?");
add("advancements.end.enter_end_gateway.title", "Remote Getaway");
add("advancements.story.mine_stone.description", "Mine stone with your new pickaxe");
add("advancements.husbandry.root.description", "The world is full of friends and food");
add("advancements.end.dragon_egg.title", "The Next Generation");
add("advancements.toast.goal", "Goal Reached!");
add("advancements.empty", "There doesn't seem to be anything here...");
add("advancements.husbandry.tame_an_animal.title", "Best Friends Forever");
add("advancements.end.root.title", "The End");
add("advancements.husbandry.breed_an_animal.title", "The Parrots and the Bats");
add("advancements.story.mine_diamond.description", "Acquire diamonds");
add("advancements.adventure.sleep_in_bed.title", "Sweet dreams");
add("advancements.nether.return_to_sender.title", "Return to Sender");
add("advancements.story.obtain_armor.title", "Suit Up");
add("advancements.adventure.kill_a_mob.description", "Kill any hostile monster");
add("advancements.nether.all_potions.description", "Have every potion effect applied at the same time");
add("advancements.story.iron_tools.title", "Isn't It Iron Pick");
add("advancements.adventure.sleep_in_bed.description", "Change your respawn point");
add("advancements.husbandry.plant_seed.description", "Plant a seed and watch it grow");
add("advancements.husbandry.breed_an_animal.description", "Breed two animals together");
add("advancements.adventure.shoot_arrow.title", "Take Aim");
add("advancements.adventure.adventuring_time.description", "Discover every biome");
add("advancements.adventure.adventuring_time.title", "Adventuring Time");
add("advancements.nether.get_wither_skull.description", "Obtain a wither skeleton's skull");
add("advancements.adventure.summon_iron_golem.description", "Summon an Iron Golem to help defend a village");
add("advancements.nether.return_to_sender.description", "Destroy a Ghast with a fireball");
add("advancements.adventure.trade.description", "Successfully trade with a Villager");
add("advancements.story.obtain_armor.description", "Protect yourself with a piece of iron armor");
add("advancements.adventure.root.description", "Adventure, exploration and combat");
add("advancements.nether.create_beacon.title", "Bring Home the Beacon");
add("advancements.end.dragon_egg.description", "Hold the Dragon Egg");
add("advancements.nether.obtain_blaze_rod.description", "Relieve a Blaze of its rod");
add("advancements.story.lava_bucket.description", "Fill a bucket with lava");
add("advancements.story.form_obsidian.title", "Ice Bucket Challenge");
add("advancements.story.enter_the_end.title", "The End?");
add("advancements.nether.fast_travel.title", "Subspace Bubble");
add("advancements.end.enter_end_gateway.description", "Escape the island");
add("advancements.adventure.totem_of_undying.title", "Postmortal");
add("advancements.nether.all_potions.title", "A Furious Cocktail");
add("advancements.adventure.sniper_duel.title", "Sniper duel");
add("advancements.nether.summon_wither.description", "Summon the Wither");
add("advancements.adventure.totem_of_undying.description", "Use a Totem of Undying to cheat death");
add("advancements.story.shiny_gear.description", "Diamond armor saves lives");
}
private static void add(String key, String value) {
advancements.put(key, value);
}
public static String get(String key) {
return advancements.get(key);
}
}
@@ -1,340 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11_1to1_12.packets;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.Protocol1_11_1To1_12;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.data.MapColorMapping;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntArrayTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.LongArrayTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ClientboundPackets1_12;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ServerboundPackets1_12;
import com.viaversion.viaversion.protocols.protocol1_9_1_2to1_9_3_4.types.Chunk1_9_3_4Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Iterator;
import java.util.Map;
public class BlockItemPackets1_12 extends LegacyBlockItemRewriter<Protocol1_11_1To1_12> {
public BlockItemPackets1_12(Protocol1_11_1To1_12 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_12.MAP_DATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.BOOLEAN);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int count = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < count * 3; i++) {
wrapper.passthrough(Type.BYTE);
}
}
});
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
short columns = wrapper.passthrough(Type.UNSIGNED_BYTE);
if (columns <= 0) return;
short rows = wrapper.passthrough(Type.UNSIGNED_BYTE);
wrapper.passthrough(Type.UNSIGNED_BYTE); // X
wrapper.passthrough(Type.UNSIGNED_BYTE); // Z
byte[] data = wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
for (int i = 0; i < data.length; i++) {
short color = (short) (data[i] & 0xFF);
if (color > 143) {
color = (short) MapColorMapping.getNearestOldColor(color);
data[i] = (byte) color;
}
}
wrapper.write(Type.BYTE_ARRAY_PRIMITIVE, data);
}
});
}
});
registerSetSlot(ClientboundPackets1_12.SET_SLOT, Type.ITEM);
registerWindowItems(ClientboundPackets1_12.WINDOW_ITEMS, Type.ITEM_ARRAY);
registerEntityEquipment(ClientboundPackets1_12.ENTITY_EQUIPMENT, Type.ITEM);
// Plugin message Packet -> Trading
protocol.registerClientbound(ClientboundPackets1_12.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // 0 - Channel
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (wrapper.get(Type.STRING, 0).equalsIgnoreCase("MC|TrList")) {
wrapper.passthrough(Type.INT); // Passthrough Window ID
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Input Item
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Output Item
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item
if (secondItem)
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Second Item
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
}
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_9_3.CLICK_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot
map(Type.BYTE); // 2 - Button
map(Type.SHORT); // 3 - Action number
map(Type.VAR_INT); // 4 - Mode
map(Type.ITEM); // 5 - Clicked Item
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (wrapper.get(Type.VAR_INT, 0) == 1) { // Shift click
// https://github.com/ViaVersion/ViaVersion/pull/754
// Previously clients grab the item from the clicked slot *before* it has
// been moved however now they grab the slot item *after* it has been moved
// and send that in the packet.
wrapper.set(Type.ITEM, 0, null); // Set null item (probably will work)
// Apologize (may happen in some cases, maybe if inventory is full?)
PacketWrapper confirm = wrapper.create(ServerboundPackets1_12.WINDOW_CONFIRMATION);
confirm.write(Type.UNSIGNED_BYTE, wrapper.get(Type.UNSIGNED_BYTE, 0));
confirm.write(Type.SHORT, wrapper.get(Type.SHORT, 1));
confirm.write(Type.BOOLEAN, false); // Success - not used
wrapper.sendToServer(Protocol1_11_1To1_12.class);
wrapper.cancel();
confirm.sendToServer(Protocol1_11_1To1_12.class);
return;
}
Item item = wrapper.get(Type.ITEM, 0);
handleItemToServer(item);
}
});
}
});
registerCreativeInvAction(ServerboundPackets1_9_3.CREATIVE_INVENTORY_ACTION, Type.ITEM);
protocol.registerClientbound(ClientboundPackets1_12.CHUNK_DATA, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
Chunk1_9_3_4Type type = new Chunk1_9_3_4Type(clientWorld); // Use the 1.9.4 Chunk type since nothing changed.
Chunk chunk = wrapper.passthrough(type);
handleChunk(chunk);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_12.BLOCK_CHANGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Block Position
map(Type.VAR_INT); // 1 - Block
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int idx = wrapper.get(Type.VAR_INT, 0);
wrapper.set(Type.VAR_INT, 0, handleBlockID(idx));
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_12.MULTI_BLOCK_CHANGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Chunk X
map(Type.INT); // 1 - Chunk Z
map(Type.BLOCK_CHANGE_RECORD_ARRAY);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (BlockChangeRecord record : wrapper.get(Type.BLOCK_CHANGE_RECORD_ARRAY, 0)) {
record.setBlockId(handleBlockID(record.getBlockId()));
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_12.BLOCK_ENTITY_DATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION); // 0 - Position
map(Type.UNSIGNED_BYTE); // 1 - Action
map(Type.NBT); // 2 - NBT
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Remove bed color
if (wrapper.get(Type.UNSIGNED_BYTE, 0) == 11)
wrapper.cancel();
}
});
}
});
protocol.getEntityRewriter().filter().handler((event, meta) -> {
if (meta.metaType().type().equals(Type.ITEM)) // Is Item
meta.setValue(handleItemToClient((Item) meta.getValue()));
});
protocol.registerServerbound(ServerboundPackets1_9_3.CLIENT_STATUS, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Action ID
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
// Open Inventory
if (wrapper.get(Type.VAR_INT, 0) == 2) {
wrapper.cancel();
}
}
});
}
});
}
@Override
public @Nullable Item handleItemToClient(Item item) {
if (item == null) return null;
super.handleItemToClient(item);
if (item.tag() != null) {
CompoundTag backupTag = new CompoundTag();
if (handleNbtToClient(item.tag(), backupTag)) {
item.tag().put("Via|LongArrayTags", backupTag);
}
}
return item;
}
private boolean handleNbtToClient(CompoundTag compoundTag, CompoundTag backupTag) {
// Long array tags were introduced in 1.12 - just remove them
// Only save the removed tags instead of blindly copying the entire nbt again
Iterator<Map.Entry<String, Tag>> iterator = compoundTag.iterator();
boolean hasLongArrayTag = false;
while (iterator.hasNext()) {
Map.Entry<String, Tag> entry = iterator.next();
if (entry.getValue() instanceof CompoundTag) {
CompoundTag nestedBackupTag = new CompoundTag();
backupTag.put(entry.getKey(), nestedBackupTag);
hasLongArrayTag |= handleNbtToClient((CompoundTag) entry.getValue(), nestedBackupTag);
} else if (entry.getValue() instanceof LongArrayTag) {
backupTag.put(entry.getKey(), fromLongArrayTag((LongArrayTag) entry.getValue()));
iterator.remove();
hasLongArrayTag = true;
}
}
return hasLongArrayTag;
}
@Override
public @Nullable Item handleItemToServer(Item item) {
if (item == null) return null;
super.handleItemToServer(item);
if (item.tag() != null) {
Tag tag = item.tag().remove("Via|LongArrayTags");
if (tag instanceof CompoundTag) {
handleNbtToServer(item.tag(), (CompoundTag) tag);
}
}
return item;
}
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.get(entry.getKey());
handleNbtToServer(nestedTag, (CompoundTag) entry.getValue());
} else {
compoundTag.put(entry.getKey(), fromIntArrayTag((IntArrayTag) entry.getValue()));
}
}
}
private IntArrayTag fromLongArrayTag(LongArrayTag tag) {
int[] intArray = new int[tag.length() * 2];
long[] longArray = tag.getValue();
int i = 0;
for (long l : longArray) {
intArray[i++] = (int) (l >> 32);
intArray[i++] = (int) l;
}
return new IntArrayTag(intArray);
}
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++) {
longArray[j] = (long) intArray[i] << 32 | ((long) intArray[i + 1] & 0xFFFFFFFFL);
}
return new LongArrayTag(longArray);
}
}
@@ -1,65 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11_1to1_12.packets;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.libs.gson.JsonArray;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
public class ChatItemRewriter {
public static void toClient(JsonElement element, UserConnection user) {
if (element instanceof JsonObject) {
JsonObject obj = (JsonObject) element;
if (obj.has("hoverEvent")) {
if (obj.get("hoverEvent") instanceof JsonObject) {
JsonObject hoverEvent = (JsonObject) obj.get("hoverEvent");
if (hoverEvent.has("action") && hoverEvent.has("value")) {
String type = hoverEvent.get("action").getAsString();
if (type.equals("show_item") || type.equals("show_entity")) {
JsonElement value = hoverEvent.get("value");
if (value.isJsonArray()) {
JsonArray newArray = new JsonArray();
int index = 0;
for (JsonElement valueElement : value.getAsJsonArray()) {
if (valueElement.isJsonPrimitive() && valueElement.getAsJsonPrimitive().isString()) {
String newValue = index + ":" + valueElement.getAsString();
newArray.add(new JsonPrimitive(newValue));
}
}
hoverEvent.add("value", newArray);
}
}
}
}
} else if (obj.has("extra")) {
toClient(obj.get("extra"), user);
}
} else if (element instanceof JsonArray) {
JsonArray array = (JsonArray) element;
for (JsonElement value : array) {
toClient(value, user);
}
}
}
}
@@ -1,59 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11_1to1_12.packets;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.Protocol1_11_1To1_12;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.data.AdvancementTranslations;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ClientboundPackets1_12;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
public class ChatPackets1_12 extends RewriterBase<Protocol1_11_1To1_12> {
private final ComponentRewriter componentRewriter = new ComponentRewriter() {
@Override
protected void handleTranslate(JsonObject object, String translate) {
String text = AdvancementTranslations.get(translate);
if (text != null) {
object.addProperty("translate", text);
}
}
};
public ChatPackets1_12(Protocol1_11_1To1_12 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_12.CHAT_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
JsonElement element = wrapper.passthrough(Type.COMPONENT);
componentRewriter.processText(element);
});
}
});
}
}
@@ -1,316 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11_1to1_12.packets;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.Protocol1_11_1To1_12;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.data.ParrotStorage;
import com.viaversion.viabackwards.protocol.protocol1_11_1to1_12.data.ShoulderTracker;
import com.viaversion.viabackwards.utils.Block;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_12Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_12;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_12;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.protocols.protocol1_12to1_11_1.ClientboundPackets1_12;
import java.util.Optional;
public class EntityPackets1_12 extends LegacyEntityRewriter<Protocol1_11_1To1_12> {
public EntityPackets1_12(Protocol1_11_1To1_12 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_12.SPAWN_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - x
map(Type.DOUBLE); // 4 - y
map(Type.DOUBLE); // 5 - z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - data
// Track Entity
handler(getObjectTrackerHandler());
handler(getObjectRewriter(id -> Entity1_12Types.ObjectType.findById(id).orElse(null)));
// Handle FallingBlock blocks
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<Entity1_12Types.ObjectType> type = Entity1_12Types.ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (type.isPresent() && type.get() == Entity1_12Types.ObjectType.FALLING_BLOCK) {
int objectData = wrapper.get(Type.INT, 0);
int objType = objectData & 4095;
int data = objectData >> 12 & 15;
Block block = protocol.getItemRewriter().handleBlock(objType, data);
if (block == null) {
return;
}
wrapper.set(Type.INT, 0, block.getId() | block.getData() << 12);
}
}
});
}
});
registerTracker(ClientboundPackets1_12.SPAWN_EXPERIENCE_ORB, Entity1_12Types.EntityType.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_12.SPAWN_GLOBAL_ENTITY, Entity1_12Types.EntityType.WEATHER);
protocol.registerClientbound(ClientboundPackets1_12.SPAWN_MOB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Yaw
map(Type.BYTE); // 7 - Pitch
map(Type.BYTE); // 8 - Head Pitch
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
map(Types1_12.METADATA_LIST); // 12 - Metadata
// Track entity
handler(getTrackerHandler());
// Rewrite entity type / metadata
handler(getMobSpawnRewriter(Types1_12.METADATA_LIST));
}
});
registerTracker(ClientboundPackets1_12.SPAWN_PAINTING, Entity1_12Types.EntityType.PAINTING);
protocol.registerClientbound(ClientboundPackets1_12.SPAWN_PLAYER, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Player UUID
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Types1_12.METADATA_LIST); // 7 - Metadata list
handler(getTrackerAndMetaHandler(Types1_12.METADATA_LIST, Entity1_12Types.EntityType.PLAYER));
}
});
protocol.registerClientbound(ClientboundPackets1_12.JOIN_GAME, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Entity ID
map(Type.UNSIGNED_BYTE); // 1 - Gamemode
map(Type.INT); // 2 - Dimension
handler(getTrackerHandler(Entity1_12Types.EntityType.PLAYER, Type.INT));
handler(getDimensionHandler(1));
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ShoulderTracker tracker = wrapper.user().get(ShoulderTracker.class);
tracker.setEntityId(wrapper.get(Type.INT, 0));
}
});
// Send fake inventory achievement
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper packetWrapper) throws Exception {
PacketWrapper wrapper = PacketWrapper.create(0x07, null, packetWrapper.user());
wrapper.write(Type.VAR_INT, 1);
wrapper.write(Type.STRING, "achievement.openInventory");
wrapper.write(Type.VAR_INT, 1);
wrapper.scheduleSend(Protocol1_11_1To1_12.class);
}
});
}
});
registerRespawn(ClientboundPackets1_12.RESPAWN);
registerRemoveEntities(ClientboundPackets1_12.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_12.ENTITY_METADATA, Types1_12.METADATA_LIST);
protocol.registerClientbound(ClientboundPackets1_12.ENTITY_PROPERTIES, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.INT);
handler(wrapper -> {
int size = wrapper.get(Type.INT, 0);
int newSize = size;
for (int i = 0; i < size; i++) {
String key = wrapper.read(Type.STRING);
// Remove new attribute
if (key.equals("generic.flyingSpeed")) {
newSize--;
wrapper.read(Type.DOUBLE);
int modSize = wrapper.read(Type.VAR_INT);
for (int j = 0; j < modSize; j++) {
wrapper.read(Type.UUID);
wrapper.read(Type.DOUBLE);
wrapper.read(Type.BYTE);
}
} else {
wrapper.write(Type.STRING, key);
wrapper.passthrough(Type.DOUBLE);
int modSize = wrapper.passthrough(Type.VAR_INT);
for (int j = 0; j < modSize; j++) {
wrapper.passthrough(Type.UUID);
wrapper.passthrough(Type.DOUBLE);
wrapper.passthrough(Type.BYTE);
}
}
}
if (newSize != size) {
wrapper.set(Type.INT, 0, newSize);
}
});
}
});
}
@Override
protected void registerRewrites() {
mapEntityTypeWithData(Entity1_12Types.EntityType.PARROT, Entity1_12Types.EntityType.BAT).plainName().spawnMetadata(storage -> storage.add(new Metadata(12, MetaType1_12.Byte, (byte) 0x00)));
mapEntityTypeWithData(Entity1_12Types.EntityType.ILLUSION_ILLAGER, Entity1_12Types.EntityType.EVOCATION_ILLAGER).plainName();
// Handle Illager
filter().filterFamily(Entity1_12Types.EntityType.EVOCATION_ILLAGER).cancel(12);
filter().filterFamily(Entity1_12Types.EntityType.EVOCATION_ILLAGER).index(13).toIndex(12);
filter().type(Entity1_12Types.EntityType.ILLUSION_ILLAGER).index(0).handler((event, meta) -> {
byte mask = (byte) meta.getValue();
if ((mask & 0x20) == 0x20) {
mask &= ~0x20;
}
meta.setValue(mask);
});
// Create Parrot storage
filter().filterFamily(Entity1_12Types.EntityType.PARROT).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
if (!data.has(ParrotStorage.class)) {
data.put(new ParrotStorage());
}
});
// Parrot remove animal metadata
filter().type(Entity1_12Types.EntityType.PARROT).cancel(12); // Is baby
filter().type(Entity1_12Types.EntityType.PARROT).index(13).handler((event, meta) -> {
StoredEntityData data = storedEntityData(event);
ParrotStorage storage = data.get(ParrotStorage.class);
boolean isSitting = (((byte) meta.getValue()) & 0x01) == 0x01;
boolean isTamed = (((byte) meta.getValue()) & 0x04) == 0x04;
if (!storage.isTamed() && isTamed) {
// TODO do something to let the user know it's done
}
storage.setTamed(isTamed);
if (isSitting) {
event.setIndex(12);
meta.setValue((byte) 0x01);
storage.setSitting(true);
} else if (storage.isSitting()) {
event.setIndex(12);
meta.setValue((byte) 0x00);
storage.setSitting(false);
} else {
event.cancel();
}
}); // Flags (Is sitting etc, might be useful in the future
filter().type(Entity1_12Types.EntityType.PARROT).cancel(14); // Owner
filter().type(Entity1_12Types.EntityType.PARROT).cancel(15); // Variant
// Left shoulder entity data
filter().type(Entity1_12Types.EntityType.PLAYER).index(15).handler((event, meta) -> {
CompoundTag tag = (CompoundTag) meta.getValue();
ShoulderTracker tracker = event.user().get(ShoulderTracker.class);
if (tag.isEmpty() && tracker.getLeftShoulder() != null) {
tracker.setLeftShoulder(null);
tracker.update();
} else if (tag.contains("id") && event.entityId() == tracker.getEntityId()) {
String id = (String) tag.get("id").getValue();
if (tracker.getLeftShoulder() == null || !tracker.getLeftShoulder().equals(id)) {
tracker.setLeftShoulder(id);
tracker.update();
}
}
event.cancel();
});
// Right shoulder entity data
filter().type(Entity1_12Types.EntityType.PLAYER).index(16).handler((event, meta) -> {
CompoundTag tag = (CompoundTag) event.meta().getValue();
ShoulderTracker tracker = event.user().get(ShoulderTracker.class);
if (tag.isEmpty() && tracker.getRightShoulder() != null) {
tracker.setRightShoulder(null);
tracker.update();
} else if (tag.contains("id") && event.entityId() == tracker.getEntityId()) {
String id = (String) tag.get("id").getValue();
if (tracker.getRightShoulder() == null || !tracker.getRightShoulder().equals(id)) {
tracker.setRightShoulder(id);
tracker.update();
}
}
event.cancel();
});
}
@Override
public EntityType typeFromId(int typeId) {
return Entity1_12Types.getTypeFromId(typeId, false);
}
@Override
protected EntityType getObjectTypeFromId(final int typeId) {
return Entity1_12Types.getTypeFromId(typeId, true);
}
}
@@ -1,127 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11to1_11_1.packets;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_11to1_11_1.Protocol1_11To1_11_1;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_11Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_9;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
public class EntityPackets1_11_1 extends LegacyEntityRewriter<Protocol1_11To1_11_1> {
public EntityPackets1_11_1(Protocol1_11To1_11_1 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_9_3.SPAWN_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - x
map(Type.DOUBLE); // 4 - y
map(Type.DOUBLE); // 5 - z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - data
// Track Entity
handler(getObjectTrackerHandler());
handler(getObjectRewriter(id -> Entity1_11Types.ObjectType.findById(id).orElse(null)));
}
});
registerTracker(ClientboundPackets1_9_3.SPAWN_EXPERIENCE_ORB, Entity1_11Types.EntityType.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_9_3.SPAWN_GLOBAL_ENTITY, Entity1_11Types.EntityType.WEATHER);
protocol.registerClientbound(ClientboundPackets1_9_3.SPAWN_MOB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Yaw
map(Type.BYTE); // 7 - Pitch
map(Type.BYTE); // 8 - Head Pitch
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
map(Types1_9.METADATA_LIST); // 12 - Metadata
// Track entity
handler(getTrackerHandler());
// Rewrite entity type / metadata
handler(getMobSpawnRewriter(Types1_9.METADATA_LIST));
}
});
registerTracker(ClientboundPackets1_9_3.SPAWN_PAINTING, Entity1_11Types.EntityType.PAINTING);
registerJoinGame(ClientboundPackets1_9_3.JOIN_GAME, Entity1_11Types.EntityType.PLAYER);
registerRespawn(ClientboundPackets1_9_3.RESPAWN);
protocol.registerClientbound(ClientboundPackets1_9_3.SPAWN_PLAYER, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Player UUID
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Types1_9.METADATA_LIST); // 7 - Metadata list
handler(getTrackerAndMetaHandler(Types1_9.METADATA_LIST, Entity1_11Types.EntityType.PLAYER));
}
});
registerRemoveEntities(ClientboundPackets1_9_3.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_9_3.ENTITY_METADATA, Types1_9.METADATA_LIST);
}
@Override
protected void registerRewrites() {
// Handle non-existing firework metadata (index 7 entity id for boosting)
filter().type(Entity1_11Types.EntityType.FIREWORK).cancel(7);
// Handle non-existing pig metadata (index 14 - boost time)
filter().type(Entity1_11Types.EntityType.PIG).cancel(14);
}
@Override
public EntityType typeFromId(int typeId) {
return Entity1_11Types.getTypeFromId(typeId, false);
}
@Override
protected EntityType getObjectTypeFromId(final int typeId) {
return Entity1_11Types.getTypeFromId(typeId, true);
}
}
@@ -1,130 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_11to1_11_1.packets;
import com.viaversion.viabackwards.api.rewriters.LegacyBlockItemRewriter;
import com.viaversion.viabackwards.api.rewriters.LegacyEnchantmentRewriter;
import com.viaversion.viabackwards.protocol.protocol1_11to1_11_1.Protocol1_11To1_11_1;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.ServerboundPackets1_9_3;
public class ItemPackets1_11_1 extends LegacyBlockItemRewriter<Protocol1_11To1_11_1> {
private LegacyEnchantmentRewriter enchantmentRewriter;
public ItemPackets1_11_1(Protocol1_11To1_11_1 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
registerSetSlot(ClientboundPackets1_9_3.SET_SLOT, Type.ITEM);
registerWindowItems(ClientboundPackets1_9_3.WINDOW_ITEMS, Type.ITEM_ARRAY);
registerEntityEquipment(ClientboundPackets1_9_3.ENTITY_EQUIPMENT, Type.ITEM);
// Plugin message Packet -> Trading
protocol.registerClientbound(ClientboundPackets1_9_3.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // 0 - Channel
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (wrapper.get(Type.STRING, 0).equalsIgnoreCase("MC|TrList")) {
wrapper.passthrough(Type.INT); // Passthrough Window ID
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Input Item
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Output Item
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item
if (secondItem) {
wrapper.write(Type.ITEM, handleItemToClient(wrapper.read(Type.ITEM))); // Second Item
}
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
}
}
}
});
}
});
registerClickWindow(ServerboundPackets1_9_3.CLICK_WINDOW, Type.ITEM);
registerCreativeInvAction(ServerboundPackets1_9_3.CREATIVE_INVENTORY_ACTION, Type.ITEM);
// Handle item metadata
protocol.getEntityRewriter().filter().handler((event, meta) -> {
if (meta.metaType().type().equals(Type.ITEM)) { // Is Item
meta.setValue(handleItemToClient((Item) meta.getValue()));
}
});
}
@Override
protected void registerRewrites() {
enchantmentRewriter = new LegacyEnchantmentRewriter(nbtTagName);
enchantmentRewriter.registerEnchantment(22, "§7Sweeping Edge");
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
super.handleItemToClient(item);
CompoundTag tag = item.tag();
if (tag == null) return item;
if (tag.get("ench") instanceof ListTag) {
enchantmentRewriter.rewriteEnchantmentsToClient(tag, false);
}
if (tag.get("StoredEnchantments") instanceof ListTag) {
enchantmentRewriter.rewriteEnchantmentsToClient(tag, true);
}
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
super.handleItemToServer(item);
CompoundTag tag = item.tag();
if (tag == null) return item;
if (tag.contains(nbtTagName + "|ench")) {
enchantmentRewriter.rewriteEnchantmentsToServer(tag, false);
}
if (tag.contains(nbtTagName + "|StoredEnchantments")) {
enchantmentRewriter.rewriteEnchantmentsToServer(tag, true);
}
return item;
}
}
@@ -1,77 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_1to1_12_2;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ServerboundPackets1_12_1;
public class Protocol1_12_1To1_12_2 extends BackwardsProtocol<ClientboundPackets1_12_1, ClientboundPackets1_12_1, ServerboundPackets1_12_1, ServerboundPackets1_12_1> {
public Protocol1_12_1To1_12_2() {
super(ClientboundPackets1_12_1.class, ClientboundPackets1_12_1.class, ServerboundPackets1_12_1.class, ServerboundPackets1_12_1.class);
}
@Override
protected void registerPackets() {
registerClientbound(ClientboundPackets1_12_1.KEEP_ALIVE, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper packetWrapper) throws Exception {
Long keepAlive = packetWrapper.read(Type.LONG);
packetWrapper.user().get(KeepAliveTracker.class).setKeepAlive(keepAlive);
packetWrapper.write(Type.VAR_INT, keepAlive.hashCode());
}
});
}
});
registerServerbound(ServerboundPackets1_12_1.KEEP_ALIVE, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper packetWrapper) throws Exception {
int keepAlive = packetWrapper.read(Type.VAR_INT);
long realKeepAlive = packetWrapper.user().get(KeepAliveTracker.class).getKeepAlive();
if (keepAlive != Long.hashCode(realKeepAlive)) {
packetWrapper.cancel(); // Wrong data, cancel packet
return;
}
packetWrapper.write(Type.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);
}
});
}
});
}
@Override
public void init(UserConnection userConnection) {
userConnection.put(new KeepAliveTracker());
}
}
@@ -1,130 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.BackwardsMappings;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.PaintingMapping;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.packets.BlockItemPackets1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.packets.EntityPackets1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.packets.PlayerPacket1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.packets.SoundPackets1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.providers.BackwardsBlockEntityProvider;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.storage.BackwardsBlockStorage;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.storage.PlayerPositionStorage1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.storage.TabCompleteStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_13Types;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ServerboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
public class Protocol1_12_2To1_13 extends BackwardsProtocol<ClientboundPackets1_13, ClientboundPackets1_12_1, ServerboundPackets1_13, ServerboundPackets1_12_1> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings();
private final EntityRewriter entityRewriter = new EntityPackets1_13(this);
private final BlockItemPackets1_13 blockItemPackets = new BlockItemPackets1_13(this);
public Protocol1_12_2To1_13() {
super(ClientboundPackets1_13.class, ClientboundPackets1_12_1.class, ServerboundPackets1_13.class, ServerboundPackets1_12_1.class);
}
@Override
protected void registerPackets() {
executeAsyncAfterLoaded(Protocol1_13To1_12_2.class, () -> {
MAPPINGS.load();
PaintingMapping.init();
Via.getManager().getProviders().register(BackwardsBlockEntityProvider.class, new BackwardsBlockEntityProvider());
});
TranslatableRewriter translatableRewriter = new TranslatableRewriter(this) {
@Override
protected void handleTranslate(JsonObject root, String translate) {
String newTranslate = newTranslatables.get(translate);
if (newTranslate != null || (newTranslate = getMappingData().getTranslateMappings().get(translate)) != null) {
root.addProperty("translate", newTranslate);
}
}
};
translatableRewriter.registerPing();
translatableRewriter.registerBossBar(ClientboundPackets1_13.BOSSBAR);
translatableRewriter.registerChatMessage(ClientboundPackets1_13.CHAT_MESSAGE);
translatableRewriter.registerLegacyOpenWindow(ClientboundPackets1_13.OPEN_WINDOW);
translatableRewriter.registerDisconnect(ClientboundPackets1_13.DISCONNECT);
translatableRewriter.registerCombatEvent(ClientboundPackets1_13.COMBAT_EVENT);
translatableRewriter.registerTitle(ClientboundPackets1_13.TITLE);
translatableRewriter.registerTabList(ClientboundPackets1_13.TAB_LIST);
blockItemPackets.register();
entityRewriter.register();
new PlayerPacket1_13(this).register();
new SoundPackets1_13(this).register();
cancelClientbound(ClientboundPackets1_13.NBT_QUERY);
cancelClientbound(ClientboundPackets1_13.CRAFT_RECIPE_RESPONSE);
cancelClientbound(ClientboundPackets1_13.UNLOCK_RECIPES);
cancelClientbound(ClientboundPackets1_13.ADVANCEMENTS);
cancelClientbound(ClientboundPackets1_13.DECLARE_RECIPES);
cancelClientbound(ClientboundPackets1_13.TAGS);
cancelServerbound(ServerboundPackets1_12_1.CRAFT_RECIPE_REQUEST);
cancelServerbound(ServerboundPackets1_12_1.RECIPE_BOOK_DATA);
}
@Override
public void init(UserConnection user) {
// Register ClientWorld
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld(user));
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_13Types.EntityType.PLAYER));
user.put(new BackwardsBlockStorage());
user.put(new TabCompleteStorage());
if (ViaBackwards.getConfig().isFix1_13FacePlayer() && !user.has(PlayerPositionStorage1_13.class)) {
user.put(new PlayerPositionStorage1_13());
}
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityRewriter getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPackets1_13 getItemRewriter() {
return blockItemPackets;
}
}
@@ -1,43 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13.block_entity_handlers;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.EntityNameRewrites;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.providers.BackwardsBlockEntityProvider;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
public class SpawnerHandler implements BackwardsBlockEntityProvider.BackwardsBlockEntityHandler {
@Override
public CompoundTag transform(UserConnection user, int blockId, CompoundTag tag) {
Tag dataTag = tag.get("SpawnData");
if (dataTag instanceof CompoundTag) {
CompoundTag data = (CompoundTag) dataTag;
Tag idTag = data.get("id");
if (idTag instanceof StringTag) {
StringTag s = (StringTag) idTag;
s.setValue(EntityNameRewrites.rewrite(s.getValue()));
}
}
return tag;
}
}
@@ -1,152 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13.data;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.data.VBMappings;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.IntArrayMappings;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap;
import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap;
import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.gson.JsonPrimitive;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.Protocol1_13To1_12_2;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.data.StatisticMappings;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class BackwardsMappings extends com.viaversion.viabackwards.api.data.BackwardsMappings {
private final Int2ObjectMap<String> statisticMappings = new Int2ObjectOpenHashMap<>();
private final Map<String, String> translateMappings = new HashMap<>();
private Mappings enchantmentMappings;
public BackwardsMappings() {
super("1.13", "1.12", Protocol1_13To1_12_2.class, true);
}
@Override
public void loadVBExtras(JsonObject oldMappings, JsonObject newMappings) {
enchantmentMappings = VBMappings.vbBuilder().warnOnMissing(false)
.unmapped(oldMappings.getAsJsonObject("enchantments")).mapped(newMappings.getAsJsonObject("enchantments")).build();
for (Map.Entry<String, Integer> entry : StatisticMappings.CUSTOM_STATS.entrySet()) {
statisticMappings.put(entry.getValue().intValue(), entry.getKey());
}
for (Map.Entry<String, String> entry : Protocol1_13To1_12_2.MAPPINGS.getTranslateMapping().entrySet()) {
translateMappings.put(entry.getValue(), entry.getKey());
}
}
// Has lots of compat layers, so we can't use the default Via method
private static void mapIdentifiers(int[] output, JsonObject newIdentifiers, JsonObject oldIdentifiers, JsonObject mapping) {
Object2IntMap<String> newIdentifierMap = MappingDataLoader.indexedObjectToMap(oldIdentifiers);
for (Map.Entry<String, JsonElement> entry : newIdentifiers.entrySet()) {
String key = entry.getValue().getAsString();
int value = newIdentifierMap.getInt(key);
short hardId = -1;
if (value == -1) {
JsonPrimitive replacement = mapping.getAsJsonPrimitive(key);
int propertyIndex;
if (replacement == null && (propertyIndex = key.indexOf('[')) != -1) {
replacement = mapping.getAsJsonPrimitive(key.substring(0, propertyIndex));
}
if (replacement != null) {
if (replacement.getAsString().startsWith("id:")) {
String id = replacement.getAsString().replace("id:", "");
hardId = Short.parseShort(id);
value = newIdentifierMap.getInt(oldIdentifiers.getAsJsonPrimitive(id).getAsString());
} else {
value = newIdentifierMap.getInt(replacement.getAsString());
}
}
if (value == -1) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
if (replacement != null) {
ViaBackwards.getPlatform().getLogger().warning("No key for " + entry.getValue() + "/" + replacement.getAsString() + " :( ");
} else {
ViaBackwards.getPlatform().getLogger().warning("No key for " + entry.getValue() + " :( ");
}
}
continue;
}
}
output[Integer.parseInt(entry.getKey())] = hardId != -1 ? hardId : (short) value;
}
}
@Override
protected @Nullable Mappings loadFromObject(JsonObject oldMappings, JsonObject newMappings, @Nullable JsonObject diffMappings, String key) {
if (key.equals("blockstates")) {
int[] oldToNew = new int[8582];
Arrays.fill(oldToNew, -1);
mapIdentifiers(oldToNew, oldMappings.getAsJsonObject("blockstates"), newMappings.getAsJsonObject("blocks"), diffMappings.getAsJsonObject("blockstates"));
return IntArrayMappings.of(oldToNew, -1);
} else {
return super.loadFromObject(oldMappings, newMappings, diffMappings, key);
}
}
@Override
public int getNewBlockStateId(int id) {
int mappedId = super.getNewBlockStateId(id);
// https://github.com/ViaVersion/ViaBackwards/issues/290
switch (mappedId) {
case 1595:
case 1596:
case 1597:
return 1584; // brown mushroom block
case 1611:
case 1612:
case 1613:
return 1600; // red mushroom block
default:
return mappedId;
}
}
@Override
protected int checkValidity(int id, int mappedId, String type) {
// Don't warn for missing ids here
return mappedId;
}
@Override
protected boolean shouldWarnOnMissing(String key) {
return super.shouldWarnOnMissing(key) && !key.equals("items");
}
public Int2ObjectMap<String> getStatisticMappings() {
return statisticMappings;
}
public Map<String, String> getTranslateMappings() {
return translateMappings;
}
public Mappings getEnchantmentMappings() {
return enchantmentMappings;
}
}
@@ -1,204 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13.data;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import java.util.List;
public class ParticleMapping {
private static final ParticleData[] particles;
static {
ParticleHandler blockHandler = new ParticleHandler() {
@Override
public int[] rewrite(Protocol1_12_2To1_13 protocol, PacketWrapper wrapper) throws Exception {
return rewrite(wrapper.read(Type.VAR_INT));
}
@Override
public int[] rewrite(Protocol1_12_2To1_13 protocol, List<Particle.ParticleData> data) {
return rewrite((int) data.get(0).getValue());
}
private int[] rewrite(int newType) {
int blockType = Protocol1_12_2To1_13.MAPPINGS.getNewBlockStateId(newType);
int type = blockType >> 4;
int meta = blockType & 15;
return new int[]{type + (meta << 12)};
}
@Override
public boolean isBlockHandler() {
return true;
}
};
particles = new ParticleData[]{
rewrite(16), // (0->16) minecraft:ambient_entity_effect -> mobSpellAmbient
rewrite(20), // (1->20) minecraft:angry_villager -> angryVillager
rewrite(35), // (2->35) minecraft:barrier -> barrier
rewrite(37, blockHandler),
// (3->37) minecraft:block -> blockcrack
rewrite(4), // (4->4) minecraft:bubble -> bubble
rewrite(29), // (5->29) minecraft:cloud -> cloud
rewrite(9), // (6->9) minecraft:crit -> crit
rewrite(44), // (7->44) minecraft:damage_indicator -> damageIndicator‌
rewrite(42), // (8->42) minecraft:dragon_breath -> dragonbreath
rewrite(19), // (9->19) minecraft:dripping_lava -> dripLava
rewrite(18), // (10->18) minecraft:dripping_water -> dripWater
rewrite(30, new ParticleHandler() {
@Override
public int[] rewrite(Protocol1_12_2To1_13 protocol, PacketWrapper wrapper) throws Exception {
float r = wrapper.read(Type.FLOAT);
float g = wrapper.read(Type.FLOAT);
float b = wrapper.read(Type.FLOAT);
float scale = wrapper.read(Type.FLOAT);
wrapper.set(Type.FLOAT, 3, r); // 5 - Offset X index=3
wrapper.set(Type.FLOAT, 4, g); // 6 - Offset Y index=4
wrapper.set(Type.FLOAT, 5, b); // 7 - Offset Z index=5
wrapper.set(Type.FLOAT, 6, scale); // 8 - Particle Data index=6
wrapper.set(Type.INT, 1, 0); // 9 - Particle Count index=1 enable rgb particle
return null;
}
@Override
public int[] rewrite(Protocol1_12_2To1_13 protocol, List<Particle.ParticleData> data) {
return null;
}
}), // (11->30) minecraft:dust -> reddust
rewrite(13), // (12->13) minecraft:effect -> spell
rewrite(41), // (13->41) minecraft:elder_guardian -> mobappearance
rewrite(10), // (14->10) minecraft:enchanted_hit -> magicCrit‌
rewrite(25), // (15->25) minecraft:enchant -> enchantmenttable
rewrite(43), // (16->43) minecraft:end_rod -> endRod
rewrite(15), // (17->15) minecraft:entity_effect -> mobSpell
rewrite(2), // (18->2) minecraft:explosion_emitter -> hugeexplosion
rewrite(1), // (19->1) minecraft:explosion -> largeexplode
rewrite(46, blockHandler),
// (20->46) minecraft:falling_dust -> fallingdust
rewrite(3), // (21->3) minecraft:firework -> fireworksSpark
rewrite(6), // (22->6) minecraft:fishing -> wake
rewrite(26), // (23->26) minecraft:flame -> flame
rewrite(21), // (24->21) minecraft:happy_villager -> happyVillager
rewrite(34), // (25->34) minecraft:heart -> heart
rewrite(14), // (26->14) minecraft:instant_effect -> instantSpell
rewrite(36, new ParticleHandler() {
@Override
public int[] rewrite(Protocol1_12_2To1_13 protocol, PacketWrapper wrapper) throws Exception {
return rewrite(protocol, wrapper.read(Type.FLAT_ITEM));
}
@Override
public int[] rewrite(Protocol1_12_2To1_13 protocol, List<Particle.ParticleData> data) {
return rewrite(protocol, (Item) data.get(0).getValue());
}
private int[] rewrite(Protocol1_12_2To1_13 protocol, Item newItem) {
Item item = protocol.getItemRewriter().handleItemToClient(newItem);
return new int[]{item.identifier(), item.data()};
}
}), // (27->36) minecraft:item -> iconcrack
rewrite(33), // (28->33) minecraft:item_slime -> slime
rewrite(31), // (29->31) minecraft:item_snowball -> snowballpoof
rewrite(12), // (30->12) minecraft:large_smoke -> largesmoke
rewrite(27), // (31->27) minecraft:lava -> lava
rewrite(22), // (32->22) minecraft:mycelium -> townaura
rewrite(23), // (33->23) minecraft:note -> note
rewrite(0), // (34->0) minecraft:poof -> explode
rewrite(24), // (35->24) minecraft:portal -> portal
rewrite(39), // (36->39) minecraft:rain -> droplet
rewrite(11), // (37->11) minecraft:smoke -> smoke
rewrite(48), // (38->48) minecraft:spit -> spit
rewrite(12), // (39->-1) minecraft:squid_ink -> squid_ink -> large_smoke
rewrite(45), // (40->45) minecraft:sweep_attack -> sweepAttack‌
rewrite(47), // (41->47) minecraft:totem_of_undying -> totem
rewrite(7), // (42->7) minecraft:underwater -> suspended‌
rewrite(5), // (43->5) minecraft:splash -> splash
rewrite(17), // (44->17) minecraft:witch -> witchMagic
rewrite(4), // (45->4) minecraft:bubble_pop -> bubble
rewrite(4), // (46->4) minecraft:current_down -> bubble
rewrite(4), // (47->4) minecraft:bubble_column_up -> bubble
rewrite(18), // (48->-1) minecraft:nautilus -> nautilus -> dripWater
rewrite(18), // (49->18) minecraft:dolphin -> dripWater
};
}
public static ParticleData getMapping(int id) {
return particles[id];
}
private static ParticleData rewrite(int replacementId) {
return new ParticleData(replacementId);
}
private static ParticleData rewrite(int replacementId, ParticleHandler handler) {
return new ParticleData(replacementId, handler);
}
public interface ParticleHandler {
int[] rewrite(Protocol1_12_2To1_13 protocol, PacketWrapper wrapper) throws Exception;
int[] rewrite(Protocol1_12_2To1_13 protocol, List<Particle.ParticleData> data);
default boolean isBlockHandler() {
return false;
}
}
public static final class ParticleData {
private final int historyId;
private final ParticleHandler handler;
private ParticleData(int historyId, ParticleHandler handler) {
this.historyId = historyId;
this.handler = handler;
}
private ParticleData(int historyId) {
this(historyId, null);
}
public int[] rewriteData(Protocol1_12_2To1_13 protocol, PacketWrapper wrapper) throws Exception {
if (handler == null) return null;
return handler.rewrite(protocol, wrapper);
}
public int[] rewriteMeta(Protocol1_12_2To1_13 protocol, List<Particle.ParticleData> data) {
if (handler == null) return null;
return handler.rewrite(protocol, data);
}
public int getHistoryId() {
return historyId;
}
public ParticleHandler getHandler() {
return handler;
}
}
}
@@ -1,411 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13.packets;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.entities.storage.EntityPositionHandler;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.EntityTypeMapping;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.PaintingMapping;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.ParticleMapping;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.storage.BackwardsBlockStorage;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.storage.PlayerPositionStorage1_13;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_13Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_12;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import com.viaversion.viaversion.api.type.types.version.Types1_12;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ServerboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import java.util.Optional;
public class EntityPackets1_13 extends LegacyEntityRewriter<Protocol1_12_2To1_13> {
public EntityPackets1_13(Protocol1_12_2To1_13 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_13.PLAYER_POSITION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.FLOAT);
map(Type.FLOAT);
map(Type.BYTE);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
if (!ViaBackwards.getConfig().isFix1_13FacePlayer()) return;
PlayerPositionStorage1_13 playerStorage = wrapper.user().get(PlayerPositionStorage1_13.class);
byte bitField = wrapper.get(Type.BYTE, 0);
playerStorage.setX(toSet(bitField, 0, playerStorage.getX(), wrapper.get(Type.DOUBLE, 0)));
playerStorage.setY(toSet(bitField, 1, playerStorage.getY(), wrapper.get(Type.DOUBLE, 1)));
playerStorage.setZ(toSet(bitField, 2, playerStorage.getZ(), wrapper.get(Type.DOUBLE, 2)));
}
private double toSet(int field, int bitIndex, double origin, double packetValue) {
// If bit is set, coordinate is relative
return (field & (1 << bitIndex)) != 0 ? origin + packetValue : packetValue;
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.UUID);
map(Type.BYTE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.BYTE);
map(Type.BYTE);
map(Type.INT);
handler(getObjectTrackerHandler());
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Optional<Entity1_13Types.ObjectType> optionalType = Entity1_13Types.ObjectType.findById(wrapper.get(Type.BYTE, 0));
if (!optionalType.isPresent()) return;
Entity1_13Types.ObjectType type = optionalType.get();
if (type == Entity1_13Types.ObjectType.FALLING_BLOCK) {
int blockState = wrapper.get(Type.INT, 0);
int combined = Protocol1_12_2To1_13.MAPPINGS.getNewBlockStateId(blockState);
combined = ((combined >> 4) & 0xFFF) | ((combined & 0xF) << 12);
wrapper.set(Type.INT, 0, combined);
} else if (type == Entity1_13Types.ObjectType.ITEM_FRAME) {
int data = wrapper.get(Type.INT, 0);
switch (data) {
case 3:
data = 0;
break;
case 4:
data = 1;
break;
case 5:
data = 3;
break;
}
wrapper.set(Type.INT, 0, data);
} else if (type == Entity1_13Types.ObjectType.TRIDENT) {
wrapper.set(Type.BYTE, 0, (byte) Entity1_13Types.ObjectType.TIPPED_ARROW.getId());
}
}
});
}
});
registerTracker(ClientboundPackets1_13.SPAWN_EXPERIENCE_ORB, Entity1_13Types.EntityType.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_13.SPAWN_GLOBAL_ENTITY, Entity1_13Types.EntityType.LIGHTNING_BOLT);
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_MOB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.UUID);
map(Type.VAR_INT);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.BYTE);
map(Type.BYTE);
map(Type.BYTE);
map(Type.SHORT);
map(Type.SHORT);
map(Type.SHORT);
map(Types1_13.METADATA_LIST, Types1_12.METADATA_LIST);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int type = wrapper.get(Type.VAR_INT, 1);
EntityType entityType = Entity1_13Types.getTypeFromId(type, false);
tracker(wrapper.user()).addEntity(wrapper.get(Type.VAR_INT, 0), entityType);
int oldId = EntityTypeMapping.getOldId(type);
if (oldId == -1) {
if (!hasData(entityType)) {
ViaBackwards.getPlatform().getLogger().warning("Could not find 1.12 entity type for 1.13 entity type " + type + "/" + entityType);
}
} else {
wrapper.set(Type.VAR_INT, 1, oldId);
}
}
});
// Rewrite entity type / metadata
handler(getMobSpawnRewriter(Types1_12.METADATA_LIST));
}
});
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_PLAYER, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.UUID);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.BYTE);
map(Type.BYTE);
map(Types1_13.METADATA_LIST, Types1_12.METADATA_LIST);
handler(getTrackerAndMetaHandler(Types1_12.METADATA_LIST, Entity1_13Types.EntityType.PLAYER));
}
});
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_PAINTING, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.UUID);
handler(getTrackerHandler(Entity1_13Types.EntityType.PAINTING, Type.VAR_INT));
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int motive = wrapper.read(Type.VAR_INT);
String title = PaintingMapping.getStringId(motive);
wrapper.write(Type.STRING, title);
}
});
}
});
registerJoinGame(ClientboundPackets1_13.JOIN_GAME, Entity1_13Types.EntityType.PLAYER);
protocol.registerClientbound(ClientboundPackets1_13.RESPAWN, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Dimension ID
handler(getDimensionHandler(0));
handler(wrapper -> wrapper.user().get(BackwardsBlockStorage.class).clear());
}
});
registerRemoveEntities(ClientboundPackets1_13.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_13.ENTITY_METADATA, Types1_13.METADATA_LIST, Types1_12.METADATA_LIST);
// Face Player (new packet)
protocol.registerClientbound(ClientboundPackets1_13.FACE_PLAYER, null, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.cancel();
if (!ViaBackwards.getConfig().isFix1_13FacePlayer()) return;
// We will just accept a possible, very minor mismatch between server and client position,
// and will take the server's one in both cases, else we would have to cache all entities' positions.
final int anchor = wrapper.read(Type.VAR_INT); // feet/eyes enum
final double x = wrapper.read(Type.DOUBLE);
final double y = wrapper.read(Type.DOUBLE);
final double z = wrapper.read(Type.DOUBLE);
PlayerPositionStorage1_13 positionStorage = wrapper.user().get(PlayerPositionStorage1_13.class);
// Send teleport packet to client
PacketWrapper positionAndLook = wrapper.create(ClientboundPackets1_12_1.PLAYER_POSITION);
positionAndLook.write(Type.DOUBLE, 0D);
positionAndLook.write(Type.DOUBLE, 0D);
positionAndLook.write(Type.DOUBLE, 0D);
//TODO properly cache and calculate head position?
EntityPositionHandler.writeFacingDegrees(positionAndLook, positionStorage.getX(),
anchor == 1 ? positionStorage.getY() + 1.62 : positionStorage.getY(),
positionStorage.getZ(), x, y, z);
positionAndLook.write(Type.BYTE, (byte) 7); // bitfield, 0=absolute, 1=relative - x,y,z relative, yaw,pitch absolute
positionAndLook.write(Type.VAR_INT, -1);
positionAndLook.send(Protocol1_12_2To1_13.class);
}
});
}
});
if (ViaBackwards.getConfig().isFix1_13FacePlayer()) {
PacketRemapper movementRemapper = new PacketRemapper() {
@Override
public void registerMap() {
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
handler(wrapper -> wrapper.user().get(PlayerPositionStorage1_13.class).setCoordinates(wrapper, false));
}
};
protocol.registerServerbound(ServerboundPackets1_12_1.PLAYER_POSITION, movementRemapper); // Player Position
protocol.registerServerbound(ServerboundPackets1_12_1.PLAYER_POSITION_AND_ROTATION, movementRemapper); // Player Position And Look (serverbound)
protocol.registerServerbound(ServerboundPackets1_12_1.VEHICLE_MOVE, movementRemapper); // Vehicle Move (serverbound)
}
}
@Override
protected void registerRewrites() {
// Rewrite new Entity 'drowned'
mapEntityTypeWithData(Entity1_13Types.EntityType.DROWNED, Entity1_13Types.EntityType.ZOMBIE_VILLAGER).plainName();
// Fishy
mapEntityTypeWithData(Entity1_13Types.EntityType.COD, Entity1_13Types.EntityType.SQUID).plainName();
mapEntityTypeWithData(Entity1_13Types.EntityType.SALMON, Entity1_13Types.EntityType.SQUID).plainName();
mapEntityTypeWithData(Entity1_13Types.EntityType.PUFFERFISH, Entity1_13Types.EntityType.SQUID).plainName();
mapEntityTypeWithData(Entity1_13Types.EntityType.TROPICAL_FISH, Entity1_13Types.EntityType.SQUID).plainName();
// Phantom
mapEntityTypeWithData(Entity1_13Types.EntityType.PHANTOM, Entity1_13Types.EntityType.PARROT).plainName().spawnMetadata(storage -> {
// The phantom is grey/blue so let's do yellow/blue
storage.add(new Metadata(15, MetaType1_12.VarInt, 3));
});
// Dolphin
mapEntityTypeWithData(Entity1_13Types.EntityType.DOLPHIN, Entity1_13Types.EntityType.SQUID).plainName();
// Turtle
mapEntityTypeWithData(Entity1_13Types.EntityType.TURTLE, Entity1_13Types.EntityType.OCELOT).plainName();
// Rewrite Meta types
filter().handler((event, meta) -> {
int typeId = meta.metaType().typeId();
// Rewrite optional chat to string
if (typeId == 5) {
// Json -> Legacy is done below
meta.setTypeAndValue(MetaType1_12.String, meta.getValue() != null ? meta.getValue().toString() : "");
}
// Rewrite items
else if (typeId == 6) {
Item item = (Item) meta.getValue();
meta.setTypeAndValue(MetaType1_12.Slot, protocol.getItemRewriter().handleItemToClient(item));
}
// Discontinue particles
else if (typeId == 15) {
event.cancel();
}
// Rewrite to 1.12 ids
else if (typeId > 5) {
meta.setMetaType(MetaType1_12.byId(
typeId - 1
));
}
});
// Rewrite Custom Name from Chat to String
filter().filterFamily(Entity1_13Types.EntityType.ENTITY).index(2).handler((event, meta) -> {
String value = meta.getValue().toString();
if (!value.isEmpty()) {
meta.setValue(ChatRewriter.jsonToLegacyText(value));
}
});
// Handle zombie metadata
filter().filterFamily(Entity1_13Types.EntityType.ZOMBIE).removeIndex(15);
// Handle turtle metadata (Remove them all for now)
filter().type(Entity1_13Types.EntityType.TURTLE).cancel(13); // Home pos
filter().type(Entity1_13Types.EntityType.TURTLE).cancel(14); // Has egg
filter().type(Entity1_13Types.EntityType.TURTLE).cancel(15); // Laying egg
filter().type(Entity1_13Types.EntityType.TURTLE).cancel(16); // Travel pos
filter().type(Entity1_13Types.EntityType.TURTLE).cancel(17); // Going home
filter().type(Entity1_13Types.EntityType.TURTLE).cancel(18); // Traveling
// Remove additional fish meta
filter().filterFamily(Entity1_13Types.EntityType.ABSTRACT_FISHES).cancel(12);
filter().filterFamily(Entity1_13Types.EntityType.ABSTRACT_FISHES).cancel(13);
// Remove phantom size
filter().type(Entity1_13Types.EntityType.PHANTOM).cancel(12);
// Remove boat splash timer
filter().type(Entity1_13Types.EntityType.BOAT).cancel(12);
// Remove Trident special loyalty level
filter().type(Entity1_13Types.EntityType.TRIDENT).cancel(7);
// Handle new wolf colors
filter().type(Entity1_13Types.EntityType.WOLF).index(17).handler((event, meta) -> {
meta.setValue(15 - (int) meta.getValue());
});
// Rewrite AreaEffectCloud
filter().type(Entity1_13Types.EntityType.AREA_EFFECT_CLOUD).index(9).handler((event, meta) -> {
Particle particle = (Particle) meta.getValue();
ParticleMapping.ParticleData data = ParticleMapping.getMapping(particle.getId());
int firstArg = 0;
int secondArg = 0;
int[] particleArgs = data.rewriteMeta(protocol, particle.getArguments());
if (particleArgs != null && particleArgs.length != 0) {
if (data.getHandler().isBlockHandler() && particleArgs[0] == 0) {
// Air doesn't have a break particle for sub 1.13 clients -> glass pane
particleArgs[0] = 102;
}
firstArg = particleArgs[0];
secondArg = particleArgs.length == 2 ? particleArgs[1] : 0;
}
event.createExtraMeta(new Metadata(9, MetaType1_12.VarInt, data.getHistoryId()));
event.createExtraMeta(new Metadata(10, MetaType1_12.VarInt, firstArg));
event.createExtraMeta(new Metadata(11, MetaType1_12.VarInt, secondArg));
event.cancel();
});
}
@Override
public EntityType typeFromId(int typeId) {
return Entity1_13Types.getTypeFromId(typeId, false);
}
@Override
protected EntityType getObjectTypeFromId(final int typeId) {
return Entity1_13Types.getTypeFromId(typeId, true);
}
@Override
public int newEntityId(final int newId) {
return EntityTypeMapping.getOldId(newId);
}
}
@@ -1,652 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13.packets;
import com.google.common.base.Joiner;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.ParticleMapping;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.storage.TabCompleteStorage;
import com.viaversion.viabackwards.utils.ChatUtil;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ServerboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.packets.InventoryPackets;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
public class PlayerPacket1_13 extends RewriterBase<Protocol1_12_2To1_13> {
private final CommandRewriter commandRewriter = new CommandRewriter(protocol) {
};
public PlayerPacket1_13(Protocol1_12_2To1_13 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
// Login Plugin Request
protocol.registerClientbound(State.LOGIN, 0x04, -1, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper packetWrapper) throws Exception {
packetWrapper.cancel();
packetWrapper.create(0x02, new PacketHandler() { // Plugin response
@Override
public void handle(PacketWrapper newWrapper) throws Exception {
newWrapper.write(Type.VAR_INT, packetWrapper.read(Type.VAR_INT)); // Packet id
newWrapper.write(Type.BOOLEAN, false); // Success
}
}).sendToServer(Protocol1_12_2To1_13.class);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
String channel = wrapper.read(Type.STRING);
if (channel.equals("minecraft:trader_list")) {
wrapper.write(Type.STRING, "MC|TrList");
wrapper.passthrough(Type.INT); //Passthrough Window ID
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
//Input Item
Item input = wrapper.read(Type.FLAT_ITEM);
wrapper.write(Type.ITEM, protocol.getItemRewriter().handleItemToClient(input));
//Output Item
Item output = wrapper.read(Type.FLAT_ITEM);
wrapper.write(Type.ITEM, protocol.getItemRewriter().handleItemToClient(output));
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); //Has second item
if (secondItem) {
//Second Item
Item second = wrapper.read(Type.FLAT_ITEM);
wrapper.write(Type.ITEM, protocol.getItemRewriter().handleItemToClient(second));
}
wrapper.passthrough(Type.BOOLEAN); //Trade disabled
wrapper.passthrough(Type.INT); //Number of tools uses
wrapper.passthrough(Type.INT); //Maximum number of trade uses
}
} else {
String oldChannel = InventoryPackets.getOldPluginChannelId(channel);
if (oldChannel == null) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Ignoring outgoing plugin message with channel: " + channel);
}
wrapper.cancel();
return;
}
wrapper.write(Type.STRING, oldChannel);
if (oldChannel.equals("REGISTER") || oldChannel.equals("UNREGISTER")) {
String[] channels = new String(wrapper.read(Type.REMAINING_BYTES), StandardCharsets.UTF_8).split("\0");
List<String> rewrittenChannels = new ArrayList<>();
for (String s : channels) {
String rewritten = InventoryPackets.getOldPluginChannelId(s);
if (rewritten != null) {
rewrittenChannels.add(rewritten);
} else if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Ignoring plugin channel in outgoing REGISTER: " + s);
}
}
wrapper.write(Type.REMAINING_BYTES, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
}
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_PARTICLE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Particle ID
map(Type.BOOLEAN); // 1 - Long Distance
map(Type.FLOAT); // 2 - X
map(Type.FLOAT); // 3 - Y
map(Type.FLOAT); // 4 - Z
map(Type.FLOAT); // 5 - Offset X
map(Type.FLOAT); // 6 - Offset Y
map(Type.FLOAT); // 7 - Offset Z
map(Type.FLOAT); // 8 - Particle Data
map(Type.INT); // 9 - Particle Count
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ParticleMapping.ParticleData old = ParticleMapping.getMapping(wrapper.get(Type.INT, 0));
wrapper.set(Type.INT, 0, old.getHistoryId());
int[] data = old.rewriteData(protocol, wrapper);
if (data != null) {
if (old.getHandler().isBlockHandler() && data[0] == 0) {
// Cancel air block particles
wrapper.cancel();
return;
}
for (int i : data) {
wrapper.write(Type.VAR_INT, i);
}
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.PLAYER_INFO, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper packetWrapper) throws Exception {
TabCompleteStorage storage = packetWrapper.user().get(TabCompleteStorage.class);
int action = packetWrapper.passthrough(Type.VAR_INT);
int nPlayers = packetWrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < nPlayers; i++) {
UUID uuid = packetWrapper.passthrough(Type.UUID);
if (action == 0) { // Add
String name = packetWrapper.passthrough(Type.STRING);
storage.usernames().put(uuid, name);
int nProperties = packetWrapper.passthrough(Type.VAR_INT);
for (int j = 0; j < nProperties; j++) {
packetWrapper.passthrough(Type.STRING);
packetWrapper.passthrough(Type.STRING);
if (packetWrapper.passthrough(Type.BOOLEAN)) {
packetWrapper.passthrough(Type.STRING);
}
}
packetWrapper.passthrough(Type.VAR_INT);
packetWrapper.passthrough(Type.VAR_INT);
if (packetWrapper.passthrough(Type.BOOLEAN)) {
packetWrapper.passthrough(Type.COMPONENT);
}
} else if (action == 1) { // Update Game Mode
packetWrapper.passthrough(Type.VAR_INT);
} else if (action == 2) { // Update Ping
packetWrapper.passthrough(Type.VAR_INT);
} else if (action == 3) { // Update Display Name
if (packetWrapper.passthrough(Type.BOOLEAN)) {
packetWrapper.passthrough(Type.COMPONENT);
}
} else if (action == 4) { // Remove Player
storage.usernames().remove(uuid);
}
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.SCOREBOARD_OBJECTIVE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING);
map(Type.BYTE);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
byte mode = wrapper.get(Type.BYTE, 0);
if (mode == 0 || mode == 2) {
String value = wrapper.read(Type.COMPONENT).toString();
value = ChatRewriter.jsonToLegacyText(value);
if (value.length() > 32) {
value = value.substring(0, 32);
}
wrapper.write(Type.STRING, value);
int type = wrapper.read(Type.VAR_INT);
wrapper.write(Type.STRING, type == 1 ? "hearts" : "integer");
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.TEAMS, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING);
map(Type.BYTE);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
byte action = wrapper.get(Type.BYTE, 0);
if (action == 0 || action == 2) {
String displayName = wrapper.read(Type.STRING);
displayName = ChatRewriter.jsonToLegacyText(displayName);
displayName = ChatUtil.removeUnusedColor(displayName, 'f');
if (displayName.length() > 32) {
displayName = displayName.substring(0, 32);
}
wrapper.write(Type.STRING, displayName);
byte flags = wrapper.read(Type.BYTE);
String nameTagVisibility = wrapper.read(Type.STRING);
String collisionRule = wrapper.read(Type.STRING);
int colour = wrapper.read(Type.VAR_INT);
if (colour == 21) {
colour = -1;
}
JsonElement prefixComponent = wrapper.read(Type.COMPONENT);
JsonElement suffixComponent = wrapper.read(Type.COMPONENT);
String prefix = prefixComponent == null || prefixComponent.isJsonNull() ? "" : ChatRewriter.jsonToLegacyText(prefixComponent.toString());
if (ViaBackwards.getConfig().addTeamColorTo1_13Prefix()) {
prefix += "§" + (colour > -1 && colour <= 15 ? Integer.toHexString(colour) : "r");
}
prefix = ChatUtil.removeUnusedColor(prefix, 'f', true);
if (prefix.length() > 16) prefix = prefix.substring(0, 16);
if (prefix.endsWith("§")) prefix = prefix.substring(0, prefix.length() - 1);
String suffix = suffixComponent == null || suffixComponent.isJsonNull() ? "" : ChatRewriter.jsonToLegacyText(suffixComponent.toString());
suffix = ChatUtil.removeUnusedColor(suffix, '\0'); // Don't remove white coloring
if (suffix.length() > 16) suffix = suffix.substring(0, 16);
if (suffix.endsWith("§")) suffix = suffix.substring(0, suffix.length() - 1);
wrapper.write(Type.STRING, prefix);
wrapper.write(Type.STRING, suffix);
wrapper.write(Type.BYTE, flags);
wrapper.write(Type.STRING, nameTagVisibility);
wrapper.write(Type.STRING, collisionRule);
wrapper.write(Type.BYTE, (byte) colour);
}
if (action == 0 || action == 3 || action == 4) {
wrapper.passthrough(Type.STRING_ARRAY); //Entities
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.DECLARE_COMMANDS, null, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
wrapper.cancel();
TabCompleteStorage storage = wrapper.user().get(TabCompleteStorage.class);
if (!storage.commands().isEmpty()) {
storage.commands().clear();
}
int size = wrapper.read(Type.VAR_INT);
boolean initialNodes = true;
for (int i = 0; i < size; i++) {
byte flags = wrapper.read(Type.BYTE);
wrapper.read(Type.VAR_INT_ARRAY_PRIMITIVE); // Children indices
if ((flags & 0x08) != 0) {
wrapper.read(Type.VAR_INT); // Redirect node index
}
byte nodeType = (byte) (flags & 0x03);
if (initialNodes && nodeType == 2) {
initialNodes = false;
}
if (nodeType == 1 || nodeType == 2) { // Literal/argument node
String name = wrapper.read(Type.STRING);
if (nodeType == 1 && initialNodes) {
storage.commands().add('/' + name);
}
}
if (nodeType == 2) { // Argument node
commandRewriter.handleArgument(wrapper, wrapper.read(Type.STRING));
}
if ((flags & 0x10) != 0) {
wrapper.read(Type.STRING); // Suggestion type
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.TAB_COMPLETE, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
TabCompleteStorage storage = wrapper.user().get(TabCompleteStorage.class);
if (storage.lastRequest() == null) {
wrapper.cancel();
return;
}
if (storage.lastId() != wrapper.read(Type.VAR_INT)) wrapper.cancel();
int start = wrapper.read(Type.VAR_INT);
int length = wrapper.read(Type.VAR_INT);
int lastRequestPartIndex = storage.lastRequest().lastIndexOf(' ') + 1;
if (lastRequestPartIndex != start) wrapper.cancel(); // Client only replaces after space
if (length != storage.lastRequest().length() - lastRequestPartIndex) {
wrapper.cancel(); // We can't set the length in previous versions
}
int count = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < count; i++) {
String match = wrapper.read(Type.STRING);
wrapper.write(Type.STRING, (start == 0 && !storage.isLastAssumeCommand() ? "/" : "") + match);
// Ignore tooltip
if (wrapper.read(Type.BOOLEAN)) {
wrapper.read(Type.STRING);
}
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_12_1.TAB_COMPLETE, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
TabCompleteStorage storage = wrapper.user().get(TabCompleteStorage.class);
List<String> suggestions = new ArrayList<>();
String command = wrapper.read(Type.STRING);
boolean assumeCommand = wrapper.read(Type.BOOLEAN);
wrapper.read(Type.OPTIONAL_POSITION);
if (!assumeCommand && !command.startsWith("/")) {
// Complete usernames for non-commands
String buffer = command.substring(command.lastIndexOf(' ') + 1);
for (String value : storage.usernames().values()) {
if (startsWithIgnoreCase(value, buffer)) {
suggestions.add(value);
}
}
} else if (!storage.commands().isEmpty() && !command.contains(" ")) {
// Complete commands names with values from 'Declare Commands' packet
for (String value : storage.commands()) {
if (startsWithIgnoreCase(value, command)) {
suggestions.add(value);
}
}
}
if (!suggestions.isEmpty()) {
wrapper.cancel();
PacketWrapper response = wrapper.create(ClientboundPackets1_12_1.TAB_COMPLETE);
response.write(Type.VAR_INT, suggestions.size());
for (String value : suggestions) {
response.write(Type.STRING, value);
}
response.scheduleSend(Protocol1_12_2To1_13.class);
storage.setLastRequest(null);
return;
}
if (!assumeCommand && command.startsWith("/")) {
command = command.substring(1);
}
int id = ThreadLocalRandom.current().nextInt();
wrapper.write(Type.VAR_INT, id);
wrapper.write(Type.STRING, command);
storage.setLastId(id);
storage.setLastAssumeCommand(assumeCommand);
storage.setLastRequest(command);
});
}
});
protocol.registerServerbound(ServerboundPackets1_12_1.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
String channel = wrapper.read(Type.STRING);
switch (channel) {
case "MC|BSign":
case "MC|BEdit":
wrapper.setId(0x0B);
Item book = wrapper.read(Type.ITEM);
wrapper.write(Type.FLAT_ITEM, protocol.getItemRewriter().handleItemToServer(book));
boolean signing = channel.equals("MC|BSign");
wrapper.write(Type.BOOLEAN, signing);
break;
case "MC|ItemName":
wrapper.setId(0x1C);
break;
case "MC|AdvCmd":
byte type = wrapper.read(Type.BYTE);
if (type == 0) {
//Information from https://wiki.vg/index.php?title=Plugin_channels&oldid=14089
//The Notchain client only uses this for command block minecarts and uses MC|AutoCmd for blocks, but the Notchian server still accepts it for either.
//Maybe older versions used this and we need to implement this? The issues is that we would have to save the command block types
wrapper.setId(0x22);
wrapper.cancel();
ViaBackwards.getPlatform().getLogger().warning("Client send MC|AdvCmd custom payload to update command block, weird!");
} else if (type == 1) {
wrapper.setId(0x23);
wrapper.write(Type.VAR_INT, wrapper.read(Type.INT)); //Entity Id
wrapper.passthrough(Type.STRING); //Command
wrapper.passthrough(Type.BOOLEAN); //Track Output
} else {
wrapper.cancel();
}
break;
case "MC|AutoCmd": {
wrapper.setId(0x22);
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.INT);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION, new Position(x, (short) y, z));
wrapper.passthrough(Type.STRING); //Command
byte flags = 0;
if (wrapper.read(Type.BOOLEAN)) flags |= 0x01; //Track Output
String mode = wrapper.read(Type.STRING);
int modeId = mode.equals("SEQUENCE") ? 0 : mode.equals("AUTO") ? 1 : 2;
wrapper.write(Type.VAR_INT, modeId);
if (wrapper.read(Type.BOOLEAN)) flags |= 0x02; //Is conditional
if (wrapper.read(Type.BOOLEAN)) flags |= 0x04; //Automatic
wrapper.write(Type.BYTE, flags);
break;
}
case "MC|Struct": {
wrapper.setId(0x25);
int x = wrapper.read(Type.INT);
int y = wrapper.read(Type.INT);
int z = wrapper.read(Type.INT);
wrapper.write(Type.POSITION, new Position(x, (short) y, z));
wrapper.write(Type.VAR_INT, wrapper.read(Type.BYTE) - 1);
String mode = wrapper.read(Type.STRING);
int modeId = mode.equals("SAVE") ? 0 : mode.equals("LOAD") ? 1 : mode.equals("CORNER") ? 2 : 3;
wrapper.write(Type.VAR_INT, modeId);
wrapper.passthrough(Type.STRING); //Name
wrapper.write(Type.BYTE, wrapper.read(Type.INT).byteValue()); //Offset X
wrapper.write(Type.BYTE, wrapper.read(Type.INT).byteValue()); //Offset Y
wrapper.write(Type.BYTE, wrapper.read(Type.INT).byteValue()); //Offset Z
wrapper.write(Type.BYTE, wrapper.read(Type.INT).byteValue()); //Size X
wrapper.write(Type.BYTE, wrapper.read(Type.INT).byteValue()); //Size Y
wrapper.write(Type.BYTE, wrapper.read(Type.INT).byteValue()); //Size Z
String mirror = wrapper.read(Type.STRING);
int mirrorId = mode.equals("NONE") ? 0 : mode.equals("LEFT_RIGHT") ? 1 : 2;
String rotation = wrapper.read(Type.STRING);
int rotationId = mode.equals("NONE") ? 0 : mode.equals("CLOCKWISE_90") ? 1 : mode.equals("CLOCKWISE_180") ? 2 : 3;
wrapper.passthrough(Type.STRING); //Metadata
byte flags = 0;
if (wrapper.read(Type.BOOLEAN)) flags |= 0x01; //Ignore entities
if (wrapper.read(Type.BOOLEAN)) flags |= 0x02; //Show air
if (wrapper.read(Type.BOOLEAN)) flags |= 0x04; //Show bounding box
wrapper.passthrough(Type.FLOAT); //Integrity
wrapper.passthrough(Type.VAR_LONG); //Seed
wrapper.write(Type.BYTE, flags);
break;
}
case "MC|Beacon":
wrapper.setId(0x20);
wrapper.write(Type.VAR_INT, wrapper.read(Type.INT)); //Primary Effect
wrapper.write(Type.VAR_INT, wrapper.read(Type.INT)); //Secondary Effect
break;
case "MC|TrSel":
wrapper.setId(0x1F);
wrapper.write(Type.VAR_INT, wrapper.read(Type.INT)); //Slot
break;
case "MC|PickItem":
wrapper.setId(0x15);
break;
default:
String newChannel = InventoryPackets.getNewPluginChannelId(channel);
if (newChannel == null) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Ignoring incoming plugin message with channel: " + channel);
}
wrapper.cancel();
return;
}
wrapper.write(Type.STRING, newChannel);
if (newChannel.equals("minecraft:register") || newChannel.equals("minecraft:unregister")) {
String[] channels = new String(wrapper.read(Type.REMAINING_BYTES), StandardCharsets.UTF_8).split("\0");
List<String> rewrittenChannels = new ArrayList<>();
for (String s : channels) {
String rewritten = InventoryPackets.getNewPluginChannelId(s);
if (rewritten != null) {
rewrittenChannels.add(rewritten);
} else if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Ignoring plugin channel in incoming REGISTER: " + s);
}
}
if (!rewrittenChannels.isEmpty()) {
wrapper.write(Type.REMAINING_BYTES, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
} else {
wrapper.cancel();
return;
}
}
break;
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.STATISTICS, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int size = wrapper.get(Type.VAR_INT, 0);
int newSize = size;
for (int i = 0; i < size; i++) {
int categoryId = wrapper.read(Type.VAR_INT);
int statisticId = wrapper.read(Type.VAR_INT);
String name = "";
// categories 0-7 (items, blocks, entities) - probably not feasible
switch (categoryId) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
wrapper.read(Type.VAR_INT); // remove value
newSize--;
continue;
case 8:
name = protocol.getMappingData().getStatisticMappings().get(statisticId);
if (name == null) {
wrapper.read(Type.VAR_INT);
newSize--;
continue;
}
break;
}
wrapper.write(Type.STRING, name); // string id
wrapper.passthrough(Type.VAR_INT); // value
}
if (newSize != size) {
wrapper.set(Type.VAR_INT, 0, newSize);
}
}
});
}
});
}
private static boolean startsWithIgnoreCase(String string, String prefix) {
if (string.length() < prefix.length()) {
return false;
}
return string.regionMatches(true, 0, prefix, 0, prefix.length());
}
}
@@ -1,102 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13.packets;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.data.NamedSoundMapping;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_12_1to1_12.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
public class SoundPackets1_13 extends RewriterBase<Protocol1_12_2To1_13> {
private static final String[] SOUND_SOURCES = {"master", "music", "record", "weather", "block", "hostile", "neutral", "player", "ambient", "voice"};
public SoundPackets1_13(Protocol1_12_2To1_13 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_13.NAMED_SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING);
handler(wrapper -> {
String newSound = wrapper.get(Type.STRING, 0);
String oldSound = NamedSoundMapping.getOldId(newSound);
if (oldSound != null || (oldSound = protocol.getMappingData().getMappedNamedSound(newSound)) != null) {
wrapper.set(Type.STRING, 0, oldSound);
} else if (!Via.getConfig().isSuppressConversionWarnings()) {
ViaBackwards.getPlatform().getLogger().warning("Unknown named sound in 1.13->1.12 protocol: " + newSound);
}
});
}
});
// Stop Sound -> Plugin Message
protocol.registerClientbound(ClientboundPackets1_13.STOP_SOUND, ClientboundPackets1_12_1.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
wrapper.write(Type.STRING, "MC|StopSound");
byte flags = wrapper.read(Type.BYTE);
String source;
if ((flags & 0x01) != 0) {
source = SOUND_SOURCES[wrapper.read(Type.VAR_INT)];
} else {
source = "";
}
String sound;
if ((flags & 0x02) != 0) {
String newSound = wrapper.read(Type.STRING);
sound = protocol.getMappingData().getMappedNamedSound(newSound);
if (sound == null) {
sound = "";
}
} else {
sound = "";
}
wrapper.write(Type.STRING, source);
wrapper.write(Type.STRING, sound);
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.SOUND, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
handler(wrapper -> {
int newSound = wrapper.get(Type.VAR_INT, 0);
int oldSound = protocol.getMappingData().getSoundMappings().getNewId(newSound);
if (oldSound == -1) {
wrapper.cancel();
} else {
wrapper.set(Type.VAR_INT, 0, oldSound);
}
});
}
});
}
}
@@ -1,111 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_12_2to1_13.providers;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.block_entity_handlers.BannerHandler;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.block_entity_handlers.BedHandler;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.block_entity_handlers.FlowerPotHandler;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.block_entity_handlers.PistonHandler;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.block_entity_handlers.SkullHandler;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.block_entity_handlers.SpawnerHandler;
import com.viaversion.viabackwards.protocol.protocol1_12_2to1_13.storage.BackwardsBlockStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.platform.providers.Provider;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.IntTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import java.util.HashMap;
import java.util.Map;
public class BackwardsBlockEntityProvider implements Provider {
private final Map<String, BackwardsBlockEntityProvider.BackwardsBlockEntityHandler> handlers = new HashMap<>();
public BackwardsBlockEntityProvider() {
handlers.put("minecraft:flower_pot", new FlowerPotHandler()); // TODO requires special treatment, manually send
handlers.put("minecraft:bed", new BedHandler());
handlers.put("minecraft:banner", new BannerHandler());
handlers.put("minecraft:skull", new SkullHandler());
handlers.put("minecraft:mob_spawner", new SpawnerHandler());
handlers.put("minecraft:piston", new PistonHandler());
}
/**
* Check if a block entity handler is present
*
* @param key Id of the NBT data ex: minecraft:bed
* @return true if present
*/
public boolean isHandled(String key) {
return handlers.containsKey(key);
}
/**
* Transform blocks to block entities!
*
* @param user The user
* @param position The position of the block entity
* @param tag The block entity tag
*/
public CompoundTag transform(UserConnection user, Position position, CompoundTag tag) throws Exception {
String id = (String) tag.get("id").getValue();
BackwardsBlockEntityHandler handler = handlers.get(id);
if (handler == null) {
if (Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Unhandled BlockEntity " + id + " full tag: " + tag);
}
return tag;
}
BackwardsBlockStorage storage = user.get(BackwardsBlockStorage.class);
Integer blockId = storage.get(position);
if (blockId == null) {
if (Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("Handled BlockEntity does not have a stored block :( " + id + " full tag: " + tag);
}
return tag;
}
return handler.transform(user, blockId, tag);
}
/**
* Transform blocks to block entities!
*
* @param user The user
* @param position The position of the block entity
* @param id The block entity id
*/
public CompoundTag transform(UserConnection user, Position position, String id) throws Exception {
CompoundTag tag = new CompoundTag();
tag.put("id", new StringTag(id));
tag.put("x", new IntTag(Math.toIntExact(position.getX())));
tag.put("y", new IntTag(Math.toIntExact(position.getY())));
tag.put("z", new IntTag(Math.toIntExact(position.getZ())));
return this.transform(user, position, tag);
}
public interface BackwardsBlockEntityHandler {
CompoundTag transform(UserConnection user, int blockId, CompoundTag tag);
}
}
@@ -1,93 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_1to1_13_2;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.protocol.protocol1_13_1to1_13_2.packets.EntityPackets1_13_2;
import com.viaversion.viabackwards.protocol.protocol1_13_1to1_13_2.packets.InventoryPackets1_13_2;
import com.viaversion.viabackwards.protocol.protocol1_13_1to1_13_2.packets.WorldPackets1_13_2;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
public class Protocol1_13_1To1_13_2 extends BackwardsProtocol<ClientboundPackets1_13, ClientboundPackets1_13, ServerboundPackets1_13, ServerboundPackets1_13> {
public Protocol1_13_1To1_13_2() {
super(ClientboundPackets1_13.class, ClientboundPackets1_13.class, ServerboundPackets1_13.class, ServerboundPackets1_13.class);
}
@Override
protected void registerPackets() {
InventoryPackets1_13_2.register(this);
WorldPackets1_13_2.register(this);
EntityPackets1_13_2.register(this);
registerServerbound(ServerboundPackets1_13.EDIT_BOOK, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.FLAT_ITEM, Type.FLAT_VAR_INT_ITEM);
}
});
registerClientbound(ClientboundPackets1_13.ADVANCEMENTS, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.BOOLEAN); // Reset/clear
int size = wrapper.passthrough(Type.VAR_INT); // Mapping size
for (int i = 0; i < size; i++) {
wrapper.passthrough(Type.STRING); // Identifier
// Parent
if (wrapper.passthrough(Type.BOOLEAN))
wrapper.passthrough(Type.STRING);
// Display data
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.COMPONENT); // Title
wrapper.passthrough(Type.COMPONENT); // Description
Item icon = wrapper.read(Type.FLAT_VAR_INT_ITEM);
wrapper.write(Type.FLAT_ITEM, icon);
wrapper.passthrough(Type.VAR_INT); // Frame type
int flags = wrapper.passthrough(Type.INT); // Flags
if ((flags & 1) != 0)
wrapper.passthrough(Type.STRING); // Background texture
wrapper.passthrough(Type.FLOAT); // X
wrapper.passthrough(Type.FLOAT); // Y
}
wrapper.passthrough(Type.STRING_ARRAY); // Criteria
int arrayLength = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < arrayLength; array++) {
wrapper.passthrough(Type.STRING_ARRAY); // String array
}
}
}
});
}
});
}
}
@@ -1,103 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_1to1_13_2.packets;
import com.viaversion.viabackwards.protocol.protocol1_13_1to1_13_2.Protocol1_13_1To1_13_2;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.api.type.types.version.Types1_13_2;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
public class EntityPackets1_13_2 {
public static void register(Protocol1_13_1To1_13_2 protocol) {
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_MOB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Entity UUID
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Yaw
map(Type.BYTE); // 7 - Pitch
map(Type.BYTE); // 8 - Head Pitch
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
map(Types1_13_2.METADATA_LIST, Types1_13.METADATA_LIST); // 12 - Metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (Metadata metadata : wrapper.get(Types1_13.METADATA_LIST, 0)) {
metadata.setMetaType(Types1_13.META_TYPES.byId(metadata.metaType().typeId()));
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_PLAYER, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Player UUID
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Types1_13_2.METADATA_LIST, Types1_13.METADATA_LIST); // 7 - Metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (Metadata metadata : wrapper.get(Types1_13.METADATA_LIST, 0)) {
metadata.setMetaType(Types1_13.META_TYPES.byId(metadata.metaType().typeId()));
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.ENTITY_METADATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Types1_13_2.METADATA_LIST, Types1_13.METADATA_LIST); // 1 - Metadata list
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (Metadata metadata : wrapper.get(Types1_13.METADATA_LIST, 0)) {
metadata.setMetaType(Types1_13.META_TYPES.byId(metadata.metaType().typeId()));
}
}
});
}
});
}
}
@@ -1,149 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_1to1_13_2.packets;
import com.viaversion.viabackwards.protocol.protocol1_13_1to1_13_2.Protocol1_13_1To1_13_2;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
public class InventoryPackets1_13_2 {
public static void register(Protocol1_13_1To1_13_2 protocol) {
protocol.registerClientbound(ClientboundPackets1_13.SET_SLOT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot ID
map(Type.FLAT_VAR_INT_ITEM, Type.FLAT_ITEM); // 2 - Slot Value
}
});
protocol.registerClientbound(ClientboundPackets1_13.WINDOW_ITEMS, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.FLAT_VAR_INT_ITEM_ARRAY, Type.FLAT_ITEM_ARRAY); // 1 - Window Values
}
});
protocol.registerClientbound(ClientboundPackets1_13.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.STRING); // Channel
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
String channel = wrapper.get(Type.STRING, 0);
if (channel.equals("minecraft:trader_list") || channel.equals("trader_list")) {
wrapper.passthrough(Type.INT); // Passthrough Window ID
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
// Input Item
wrapper.write(Type.FLAT_ITEM, wrapper.read(Type.FLAT_VAR_INT_ITEM));
// Output Item
wrapper.write(Type.FLAT_ITEM, wrapper.read(Type.FLAT_VAR_INT_ITEM));
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item
if (secondItem) {
wrapper.write(Type.FLAT_ITEM, wrapper.read(Type.FLAT_VAR_INT_ITEM));
}
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
}
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.ENTITY_EQUIPMENT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.VAR_INT); // 1 - Slot ID
map(Type.FLAT_VAR_INT_ITEM, Type.FLAT_ITEM); // 2 - Item
}
});
protocol.registerClientbound(ClientboundPackets1_13.DECLARE_RECIPES, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int recipesNo = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < recipesNo; i++) {
wrapper.passthrough(Type.STRING); // Id
String type = wrapper.passthrough(Type.STRING);
if (type.equals("crafting_shapeless")) {
wrapper.passthrough(Type.STRING); // Group
int ingredientsNo = wrapper.passthrough(Type.VAR_INT);
for (int i1 = 0; i1 < ingredientsNo; i1++) {
wrapper.write(Type.FLAT_ITEM_ARRAY_VAR_INT, wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT));
}
wrapper.write(Type.FLAT_ITEM, wrapper.read(Type.FLAT_VAR_INT_ITEM));
} else if (type.equals("crafting_shaped")) {
int ingredientsNo = wrapper.passthrough(Type.VAR_INT) * wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.STRING); // Group
for (int i1 = 0; i1 < ingredientsNo; i1++) {
wrapper.write(Type.FLAT_ITEM_ARRAY_VAR_INT, wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT));
}
wrapper.write(Type.FLAT_ITEM, wrapper.read(Type.FLAT_VAR_INT_ITEM));
} else if (type.equals("smelting")) {
wrapper.passthrough(Type.STRING); // Group
// Ingredient start
wrapper.write(Type.FLAT_ITEM_ARRAY_VAR_INT, wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT));
// Ingredient end
wrapper.write(Type.FLAT_ITEM, wrapper.read(Type.FLAT_VAR_INT_ITEM));
wrapper.passthrough(Type.FLOAT); // EXP
wrapper.passthrough(Type.VAR_INT); // Cooking time
}
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_13.CLICK_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // 0 - Window ID
map(Type.SHORT); // 1 - Slot
map(Type.BYTE); // 2 - Button
map(Type.SHORT); // 3 - Action number
map(Type.VAR_INT); // 4 - Mode
map(Type.FLAT_ITEM, Type.FLAT_VAR_INT_ITEM); // 5 - Clicked Item
}
});
protocol.registerServerbound(ServerboundPackets1_13.CREATIVE_INVENTORY_ACTION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.SHORT); // 0 - Slot
map(Type.FLAT_ITEM, Type.FLAT_VAR_INT_ITEM); // 1 - Clicked Item
}
});
}
}
@@ -1,56 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_1to1_13_2.packets;
import com.viaversion.viabackwards.protocol.protocol1_13_1to1_13_2.Protocol1_13_1To1_13_2;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
public class WorldPackets1_13_2 {
public static void register(Protocol1_13_1To1_13_2 protocol) {
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_PARTICLE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Particle ID
map(Type.BOOLEAN); // 1 - Long Distance
map(Type.FLOAT); // 2 - X
map(Type.FLOAT); // 3 - Y
map(Type.FLOAT); // 4 - Z
map(Type.FLOAT); // 5 - Offset X
map(Type.FLOAT); // 6 - Offset Y
map(Type.FLOAT); // 7 - Offset Z
map(Type.FLOAT); // 8 - Particle Data
map(Type.INT); // 9 - Particle Count
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int id = wrapper.get(Type.INT, 0);
if (id == 27) {
wrapper.write(Type.FLAT_ITEM, wrapper.read(Type.FLAT_VAR_INT_ITEM));
}
}
});
}
});
}
}
@@ -1,214 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_2to1_14;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.data.CommandRewriter1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.packets.BlockItemPackets1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.packets.EntityPackets1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.packets.PlayerPackets1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.packets.SoundPackets1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.storage.ChunkLightStorage;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_14Types;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ServerboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
public class Protocol1_13_2To1_14 extends BackwardsProtocol<ClientboundPackets1_14, ClientboundPackets1_13, ServerboundPackets1_14, ServerboundPackets1_13> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.14", "1.13.2", Protocol1_14To1_13_2.class, true);
private final EntityRewriter entityRewriter = new EntityPackets1_14(this);
private BlockItemPackets1_14 blockItemPackets;
public Protocol1_13_2To1_14() {
super(ClientboundPackets1_14.class, ClientboundPackets1_13.class, ServerboundPackets1_14.class, ServerboundPackets1_13.class);
}
@Override
protected void registerPackets() {
executeAsyncAfterLoaded(Protocol1_14To1_13_2.class, MAPPINGS::load);
TranslatableRewriter translatableRewriter = new TranslatableRewriter(this);
translatableRewriter.registerBossBar(ClientboundPackets1_14.BOSSBAR);
translatableRewriter.registerChatMessage(ClientboundPackets1_14.CHAT_MESSAGE);
translatableRewriter.registerCombatEvent(ClientboundPackets1_14.COMBAT_EVENT);
translatableRewriter.registerDisconnect(ClientboundPackets1_14.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_14.TAB_LIST);
translatableRewriter.registerTitle(ClientboundPackets1_14.TITLE);
translatableRewriter.registerPing();
new CommandRewriter1_14(this).registerDeclareCommands(ClientboundPackets1_14.DECLARE_COMMANDS);
blockItemPackets = new BlockItemPackets1_14(this, translatableRewriter);
blockItemPackets.register();
entityRewriter.register();
new PlayerPackets1_14(this).register();
new SoundPackets1_14(this).register();
new StatisticsRewriter(this).register(ClientboundPackets1_14.STATISTICS);
cancelClientbound(ClientboundPackets1_14.UPDATE_VIEW_POSITION);
cancelClientbound(ClientboundPackets1_14.UPDATE_VIEW_DISTANCE);
cancelClientbound(ClientboundPackets1_14.ACKNOWLEDGE_PLAYER_DIGGING);
registerClientbound(ClientboundPackets1_14.TAGS, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int blockTagsSize = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < blockTagsSize; i++) {
wrapper.passthrough(Type.STRING);
int[] blockIds = wrapper.passthrough(Type.VAR_INT_ARRAY_PRIMITIVE);
for (int j = 0; j < blockIds.length; j++) {
int id = blockIds[j];
// Ignore new blocktags
int blockId = getMappingData().getNewBlockId(id);
blockIds[j] = blockId;
}
}
int itemTagsSize = wrapper.passthrough(Type.VAR_INT);
for (int i = 0; i < itemTagsSize; i++) {
wrapper.passthrough(Type.STRING);
int[] itemIds = wrapper.passthrough(Type.VAR_INT_ARRAY_PRIMITIVE);
for (int j = 0; j < itemIds.length; j++) {
int itemId = itemIds[j];
// Ignore new itemtags
int oldId = getMappingData().getItemMappings().get(itemId);
itemIds[j] = oldId;
}
}
int fluidTagsSize = wrapper.passthrough(Type.VAR_INT); // fluid tags
for (int i = 0; i < fluidTagsSize; i++) {
wrapper.passthrough(Type.STRING);
wrapper.passthrough(Type.VAR_INT_ARRAY_PRIMITIVE);
}
// Eat entity tags
int entityTagsSize = wrapper.read(Type.VAR_INT);
for (int i = 0; i < entityTagsSize; i++) {
wrapper.read(Type.STRING);
wrapper.read(Type.VAR_INT_ARRAY_PRIMITIVE);
}
}
});
}
});
registerClientbound(ClientboundPackets1_14.UPDATE_LIGHT, null, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int x = wrapper.read(Type.VAR_INT);
int z = wrapper.read(Type.VAR_INT);
int skyLightMask = wrapper.read(Type.VAR_INT);
int blockLightMask = wrapper.read(Type.VAR_INT);
int emptySkyLightMask = wrapper.read(Type.VAR_INT);
int emptyBlockLightMask = wrapper.read(Type.VAR_INT);
byte[][] skyLight = new byte[16][];
// we don't need void and +256 light
if (isSet(skyLightMask, 0)) {
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
}
for (int i = 0; i < 16; i++) {
if (isSet(skyLightMask, i + 1)) {
skyLight[i] = wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
} else if (isSet(emptySkyLightMask, i + 1)) {
skyLight[i] = ChunkLightStorage.EMPTY_LIGHT;
}
}
if (isSet(skyLightMask, 17)) {
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
}
byte[][] blockLight = new byte[16][];
if (isSet(blockLightMask, 0)) {
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
}
for (int i = 0; i < 16; i++) {
if (isSet(blockLightMask, i + 1)) {
blockLight[i] = wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
} else if (isSet(emptyBlockLightMask, i + 1)) {
blockLight[i] = ChunkLightStorage.EMPTY_LIGHT;
}
}
if (isSet(blockLightMask, 17)) {
wrapper.read(Type.BYTE_ARRAY_PRIMITIVE);
}
//TODO Soft memory leak: Don't store light if chunk is already loaded
wrapper.user().get(ChunkLightStorage.class).setStoredLight(skyLight, blockLight, x, z);
wrapper.cancel();
}
private boolean isSet(int mask, int i) {
return (mask & (1 << i)) != 0;
}
});
}
});
}
@Override
public void init(UserConnection user) {
// Register ClientWorld
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld(user));
}
user.addEntityTracker(this.getClass(), new EntityTrackerBase(user, Entity1_14Types.PLAYER, true));
if (!user.has(ChunkLightStorage.class)) {
user.put(new ChunkLightStorage(user));
}
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityRewriter getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPackets1_14 getItemRewriter() {
return blockItemPackets;
}
}
@@ -1,599 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_2to1_14.packets;
import com.google.common.collect.ImmutableSet;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.EnchantmentRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.storage.ChunkLightStorage;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.Environment;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLight;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLightImpl;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_14Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.api.type.types.version.Types1_13_2;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.ListTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag;
import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.data.RecipeRewriter1_13_2;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.types.Chunk1_13Type;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.Protocol1_14To1_13_2;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.types.Chunk1_14Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeRewriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class BlockItemPackets1_14 extends com.viaversion.viabackwards.api.rewriters.ItemRewriter<Protocol1_13_2To1_14> {
private EnchantmentRewriter enchantmentRewriter;
public BlockItemPackets1_14(Protocol1_13_2To1_14 protocol, TranslatableRewriter translatableRewriter) {
super(protocol, translatableRewriter);
}
@Override
protected void registerPackets() {
protocol.registerServerbound(ServerboundPackets1_13.EDIT_BOOK, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> handleItemToServer(wrapper.passthrough(Type.FLAT_VAR_INT_ITEM)));
}
});
protocol.registerClientbound(ClientboundPackets1_14.OPEN_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int windowId = wrapper.read(Type.VAR_INT);
wrapper.write(Type.UNSIGNED_BYTE, (short) windowId);
int type = wrapper.read(Type.VAR_INT);
String stringType = null;
String containerTitle = null;
int slotSize = 0;
if (type < 6) {
if (type == 2) containerTitle = "Barrel";
stringType = "minecraft:container";
slotSize = (type + 1) * 9;
} else {
switch (type) {
case 11:
stringType = "minecraft:crafting_table";
break;
case 9: //blast furnace
case 20: //smoker
case 13: //furnace
case 14: //grindstone
if (type == 9) containerTitle = "Blast Furnace";
else if (type == 20) containerTitle = "Smoker";
else if (type == 14) containerTitle = "Grindstone";
stringType = "minecraft:furnace";
slotSize = 3;
break;
case 6:
stringType = "minecraft:dropper";
slotSize = 9;
break;
case 12:
stringType = "minecraft:enchanting_table";
break;
case 10:
stringType = "minecraft:brewing_stand";
slotSize = 5;
break;
case 18:
stringType = "minecraft:villager";
break;
case 8:
stringType = "minecraft:beacon";
slotSize = 1;
break;
case 21: //cartography_table
case 7:
if (type == 21) containerTitle = "Cartography Table";
stringType = "minecraft:anvil";
break;
case 15:
stringType = "minecraft:hopper";
slotSize = 5;
break;
case 19:
stringType = "minecraft:shulker_box";
slotSize = 27;
break;
}
}
if (stringType == null) {
ViaBackwards.getPlatform().getLogger().warning("Can't open inventory for 1.13 player! Type: " + type);
wrapper.cancel();
return;
}
wrapper.write(Type.STRING, stringType);
JsonElement title = wrapper.read(Type.COMPONENT);
if (containerTitle != null) {
// Don't rewrite renamed, only translatable titles
JsonObject object;
if (title.isJsonObject() && (object = title.getAsJsonObject()).has("translate")) {
// Don't rewrite other 9x3 translatable containers
if (type != 2 || object.getAsJsonPrimitive("translate").getAsString().equals("container.barrel")) {
title = ChatRewriter.legacyTextToJson(containerTitle);
}
}
}
wrapper.write(Type.COMPONENT, title);
wrapper.write(Type.UNSIGNED_BYTE, (short) slotSize);
}
});
}
});
// Horse window -> Open Window
protocol.registerClientbound(ClientboundPackets1_14.OPEN_HORSE_WINDOW, ClientboundPackets1_13.OPEN_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.UNSIGNED_BYTE); // Window id
wrapper.write(Type.STRING, "EntityHorse"); // Type
JsonObject object = new JsonObject();
object.addProperty("translate", "minecraft.horse");
wrapper.write(Type.COMPONENT, object); // Title
wrapper.write(Type.UNSIGNED_BYTE, wrapper.read(Type.VAR_INT).shortValue()); // Number of slots
wrapper.passthrough(Type.INT); // Entity id
}
});
}
});
BlockRewriter blockRewriter = new BlockRewriter(protocol, Type.POSITION);
registerSetCooldown(ClientboundPackets1_14.COOLDOWN);
registerWindowItems(ClientboundPackets1_14.WINDOW_ITEMS, Type.FLAT_VAR_INT_ITEM_ARRAY);
registerSetSlot(ClientboundPackets1_14.SET_SLOT, Type.FLAT_VAR_INT_ITEM);
registerAdvancements(ClientboundPackets1_14.ADVANCEMENTS, Type.FLAT_VAR_INT_ITEM);
// Trade List -> Plugin Message
protocol.registerClientbound(ClientboundPackets1_14.TRADE_LIST, ClientboundPackets1_13.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.STRING, "minecraft:trader_list");
int windowId = wrapper.read(Type.VAR_INT);
wrapper.write(Type.INT, windowId);
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
// Input Item
Item input = wrapper.read(Type.FLAT_VAR_INT_ITEM);
input = handleItemToClient(input);
wrapper.write(Type.FLAT_VAR_INT_ITEM, input);
// Output Item
Item output = wrapper.read(Type.FLAT_VAR_INT_ITEM);
output = handleItemToClient(output);
wrapper.write(Type.FLAT_VAR_INT_ITEM, output);
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); // Has second item
if (secondItem) {
// Second Item
Item second = wrapper.read(Type.FLAT_VAR_INT_ITEM);
second = handleItemToClient(second);
wrapper.write(Type.FLAT_VAR_INT_ITEM, second);
}
wrapper.passthrough(Type.BOOLEAN); // Trade disabled
wrapper.passthrough(Type.INT); // Number of tools uses
wrapper.passthrough(Type.INT); // Maximum number of trade uses
wrapper.read(Type.INT);
wrapper.read(Type.INT);
wrapper.read(Type.FLOAT);
}
wrapper.read(Type.VAR_INT);
wrapper.read(Type.VAR_INT);
wrapper.read(Type.BOOLEAN);
}
});
}
});
// Open Book -> Plugin Message
protocol.registerClientbound(ClientboundPackets1_14.OPEN_BOOK, ClientboundPackets1_13.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.STRING, "minecraft:book_open");
wrapper.passthrough(Type.VAR_INT);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.ENTITY_EQUIPMENT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.VAR_INT); // 1 - Slot ID
map(Type.FLAT_VAR_INT_ITEM); // 2 - Item
handler(itemToClientHandler(Type.FLAT_VAR_INT_ITEM));
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int entityId = wrapper.get(Type.VAR_INT, 0);
EntityType entityType = wrapper.user().getEntityTracker(Protocol1_13_2To1_14.class).entityType(entityId);
if (entityType == null) return;
if (entityType.isOrHasParent(Entity1_14Types.ABSTRACT_HORSE)) {
wrapper.setId(0x3F);
wrapper.resetReader();
wrapper.passthrough(Type.VAR_INT);
wrapper.read(Type.VAR_INT);
Item item = wrapper.read(Type.FLAT_VAR_INT_ITEM);
int armorType = item == null || item.identifier() == 0 ? 0 : item.identifier() - 726;
if (armorType < 0 || armorType > 3) {
ViaBackwards.getPlatform().getLogger().warning("Received invalid horse armor: " + item);
wrapper.cancel();
return;
}
List<Metadata> metadataList = new ArrayList<>();
metadataList.add(new Metadata(16, Types1_13_2.META_TYPES.varIntType, armorType));
wrapper.write(Types1_13.METADATA_LIST, metadataList);
}
}
});
}
});
RecipeRewriter recipeHandler = new RecipeRewriter1_13_2(protocol);
protocol.registerClientbound(ClientboundPackets1_14.DECLARE_RECIPES, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
private final Set<String> removedTypes = ImmutableSet.of("crafting_special_suspiciousstew", "blasting", "smoking", "campfire_cooking", "stonecutting");
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int size = wrapper.passthrough(Type.VAR_INT);
int deleted = 0;
for (int i = 0; i < size; i++) {
String type = wrapper.read(Type.STRING);
String id = wrapper.read(Type.STRING); // Recipe Identifier
type = type.replace("minecraft:", "");
if (removedTypes.contains(type)) {
switch (type) {
case "blasting":
case "smoking":
case "campfire_cooking":
wrapper.read(Type.STRING); // Group
wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients
wrapper.read(Type.FLAT_VAR_INT_ITEM);
wrapper.read(Type.FLOAT); // EXP
wrapper.read(Type.VAR_INT); // Cooking time
break;
case "stonecutting":
wrapper.read(Type.STRING); // Group?
wrapper.read(Type.FLAT_VAR_INT_ITEM_ARRAY_VAR_INT); // Ingredients
wrapper.read(Type.FLAT_VAR_INT_ITEM); // Result
break;
}
deleted++;
continue;
}
wrapper.write(Type.STRING, id);
wrapper.write(Type.STRING, type);
// Handle the rest of the types
recipeHandler.handle(wrapper, type);
}
wrapper.set(Type.VAR_INT, 0, size - deleted);
}
});
}
});
registerClickWindow(ServerboundPackets1_13.CLICK_WINDOW, Type.FLAT_VAR_INT_ITEM);
registerCreativeInvAction(ServerboundPackets1_13.CREATIVE_INVENTORY_ACTION, Type.FLAT_VAR_INT_ITEM);
protocol.registerClientbound(ClientboundPackets1_14.BLOCK_BREAK_ANIMATION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.POSITION1_14, Type.POSITION);
map(Type.BYTE);
}
});
protocol.registerClientbound(ClientboundPackets1_14.BLOCK_ENTITY_DATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION1_14, Type.POSITION);
}
});
protocol.registerClientbound(ClientboundPackets1_14.BLOCK_ACTION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION1_14, Type.POSITION); // Location
map(Type.UNSIGNED_BYTE); // Action id
map(Type.UNSIGNED_BYTE); // Action param
map(Type.VAR_INT); // Block id - /!\ NOT BLOCK STATE
handler(wrapper -> {
int mappedId = protocol.getMappingData().getNewBlockId(wrapper.get(Type.VAR_INT, 0));
if (mappedId == -1) {
wrapper.cancel();
return;
}
wrapper.set(Type.VAR_INT, 0, mappedId);
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.BLOCK_CHANGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION1_14, Type.POSITION);
map(Type.VAR_INT);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int id = wrapper.get(Type.VAR_INT, 0);
wrapper.set(Type.VAR_INT, 0, protocol.getMappingData().getNewBlockStateId(id));
}
});
}
});
blockRewriter.registerMultiBlockChange(ClientboundPackets1_14.MULTI_BLOCK_CHANGE);
protocol.registerClientbound(ClientboundPackets1_14.EXPLOSION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.FLOAT); // X
map(Type.FLOAT); // Y
map(Type.FLOAT); // Z
map(Type.FLOAT); // Radius
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
for (int i = 0; i < 3; i++) {
float coord = wrapper.get(Type.FLOAT, i);
if (coord < 0f) {
coord = (float) Math.floor(coord);
wrapper.set(Type.FLOAT, i, coord);
}
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.CHUNK_DATA, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
Chunk chunk = wrapper.read(new Chunk1_14Type());
wrapper.write(new Chunk1_13Type(clientWorld), chunk);
ChunkLightStorage.ChunkLight chunkLight = wrapper.user().get(ChunkLightStorage.class).getStoredLight(chunk.getX(), chunk.getZ());
for (int i = 0; i < chunk.getSections().length; i++) {
ChunkSection section = chunk.getSections()[i];
if (section == null) continue;
ChunkSectionLight sectionLight = new ChunkSectionLightImpl();
section.setLight(sectionLight);
if (chunkLight == null) {
sectionLight.setBlockLight(ChunkLightStorage.FULL_LIGHT);
if (clientWorld.getEnvironment() == Environment.NORMAL) {
sectionLight.setSkyLight(ChunkLightStorage.FULL_LIGHT);
}
} else {
byte[] blockLight = chunkLight.getBlockLight()[i];
sectionLight.setBlockLight(blockLight != null ? blockLight : ChunkLightStorage.FULL_LIGHT);
if (clientWorld.getEnvironment() == Environment.NORMAL) {
byte[] skyLight = chunkLight.getSkyLight()[i];
sectionLight.setSkyLight(skyLight != null ? skyLight : ChunkLightStorage.FULL_LIGHT);
}
}
if (Via.getConfig().isNonFullBlockLightFix() && section.getNonAirBlocksCount() != 0 && sectionLight.hasBlockLight()) {
for (int x = 0; x < 16; x++) {
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
int id = section.getFlatBlock(x, y, z);
if (Protocol1_14To1_13_2.MAPPINGS.getNonFullBlocks().contains(id)) {
sectionLight.getBlockLightNibbleArray().set(x, y, z, 0);
}
}
}
}
}
for (int j = 0; j < section.getPaletteSize(); j++) {
int old = section.getPaletteEntry(j);
int newId = protocol.getMappingData().getNewBlockStateId(old);
section.setPaletteEntry(j, newId);
}
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.UNLOAD_CHUNK, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int x = wrapper.passthrough(Type.INT);
int z = wrapper.passthrough(Type.INT);
wrapper.user().get(ChunkLightStorage.class).unloadChunk(x, z);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.EFFECT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // Effect Id
map(Type.POSITION1_14, Type.POSITION); // Location
map(Type.INT); // Data
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int id = wrapper.get(Type.INT, 0);
int data = wrapper.get(Type.INT, 1);
if (id == 1010) { // Play record
wrapper.set(Type.INT, 1, protocol.getMappingData().getNewItemId(data));
} else if (id == 2001) { // Block break + block break sound
wrapper.set(Type.INT, 1, protocol.getMappingData().getNewBlockStateId(data));
}
}
});
}
});
registerSpawnParticle(ClientboundPackets1_14.SPAWN_PARTICLE, Type.FLAT_VAR_INT_ITEM, Type.FLOAT);
protocol.registerClientbound(ClientboundPackets1_14.MAP_DATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.BYTE);
map(Type.BOOLEAN);
map(Type.BOOLEAN, Type.NOTHING); // Locked
}
});
protocol.registerClientbound(ClientboundPackets1_14.SPAWN_POSITION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION1_14, Type.POSITION);
}
});
}
@Override
protected void registerRewrites() {
enchantmentRewriter = new EnchantmentRewriter(this, false);
enchantmentRewriter.registerEnchantment("minecraft:multishot", "§7Multishot");
enchantmentRewriter.registerEnchantment("minecraft:quick_charge", "§7Quick Charge");
enchantmentRewriter.registerEnchantment("minecraft:piercing", "§7Piercing");
}
@Override
public Item handleItemToClient(Item item) {
if (item == null) return null;
super.handleItemToClient(item);
// Lore now uses JSON
CompoundTag tag = item.tag();
CompoundTag display;
if (tag != null && (display = tag.get("display")) != null) {
ListTag lore = display.get("Lore");
if (lore != null) {
saveListTag(display, lore, "Lore");
for (Tag loreEntry : lore) {
if (!(loreEntry instanceof StringTag)) continue;
StringTag loreEntryTag = (StringTag) loreEntry;
String value = loreEntryTag.getValue();
if (value != null && !value.isEmpty()) {
loreEntryTag.setValue(ChatRewriter.jsonToLegacyText(value));
}
}
}
}
enchantmentRewriter.handleToClient(item);
return item;
}
@Override
public Item handleItemToServer(Item item) {
if (item == null) return null;
// Lore now uses JSON
CompoundTag tag = item.tag();
CompoundTag display;
if (tag != null && (display = tag.get("display")) != null) {
// Transform to json if no backup tag is found (else process that in the super method)
ListTag lore = display.get("Lore");
if (lore != null && !hasBackupTag(display, "Lore")) {
for (Tag loreEntry : lore) {
if (loreEntry instanceof StringTag) {
StringTag loreEntryTag = (StringTag) loreEntry;
loreEntryTag.setValue(ChatRewriter.legacyTextToJsonString(loreEntryTag.getValue()));
}
}
}
}
enchantmentRewriter.handleToServer(item);
// Call this last to check for the backup lore above
super.handleItemToServer(item);
return item;
}
}
@@ -1,526 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_2to1_14.packets;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.entities.storage.EntityData;
import com.viaversion.viabackwards.api.entities.storage.EntityPositionHandler;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.storage.ChunkLightStorage;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.storage.EntityPositionStorage1_14;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.VillagerData;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_13Types;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_14Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import com.viaversion.viaversion.api.type.types.version.Types1_13_2;
import com.viaversion.viaversion.api.type.types.version.Types1_14;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.meta.MetaHandler;
public class EntityPackets1_14 extends LegacyEntityRewriter<Protocol1_13_2To1_14> {
private EntityPositionHandler positionHandler;
public EntityPackets1_14(Protocol1_13_2To1_14 protocol) {
super(protocol, Types1_13_2.META_TYPES.optionalComponentType, Types1_13_2.META_TYPES.booleanType);
}
//TODO work the method into this class alone
@Override
protected void addTrackedEntity(PacketWrapper wrapper, int entityId, EntityType type) throws Exception {
super.addTrackedEntity(wrapper, entityId, type);
// Cache the position for every newly tracked entity
if (type == Entity1_14Types.PAINTING) {
final Position position = wrapper.get(Type.POSITION, 0);
positionHandler.cacheEntityPosition(wrapper, position.getX(), position.getY(), position.getZ(), true, false);
} else if (wrapper.getId() != ClientboundPackets1_14.JOIN_GAME.getId()) { // ignore join game
positionHandler.cacheEntityPosition(wrapper, true, false);
}
}
@Override
protected void registerPackets() {
positionHandler = new EntityPositionHandler(this, EntityPositionStorage1_14.class, EntityPositionStorage1_14::new);
protocol.registerClientbound(ClientboundPackets1_14.ENTITY_STATUS, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
int entityId = wrapper.passthrough(Type.INT);
byte status = wrapper.passthrough(Type.BYTE);
// Check for death status
if (status != 3) return;
EntityTracker tracker = tracker(wrapper.user());
EntityType entityType = tracker.entityType(entityId);
if (entityType != Entity1_14Types.PLAYER) return;
// Remove equipment, else the client will see ghost items
for (int i = 0; i <= 5; i++) {
PacketWrapper equipmentPacket = wrapper.create(ClientboundPackets1_13.ENTITY_EQUIPMENT);
equipmentPacket.write(Type.VAR_INT, entityId);
equipmentPacket.write(Type.VAR_INT, i);
equipmentPacket.write(Type.FLAT_VAR_INT_ITEM, null);
equipmentPacket.send(Protocol1_13_2To1_14.class);
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.ENTITY_TELEPORT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.DOUBLE);
map(Type.DOUBLE);
map(Type.DOUBLE);
handler(wrapper -> positionHandler.cacheEntityPosition(wrapper, false, false));
}
});
PacketRemapper relativeMoveHandler = new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.SHORT);
map(Type.SHORT);
map(Type.SHORT);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
double x = wrapper.get(Type.SHORT, 0) / EntityPositionHandler.RELATIVE_MOVE_FACTOR;
double y = wrapper.get(Type.SHORT, 1) / EntityPositionHandler.RELATIVE_MOVE_FACTOR;
double z = wrapper.get(Type.SHORT, 2) / EntityPositionHandler.RELATIVE_MOVE_FACTOR;
positionHandler.cacheEntityPosition(wrapper, x, y, z, false, true);
}
});
}
};
protocol.registerClientbound(ClientboundPackets1_14.ENTITY_POSITION, relativeMoveHandler);
protocol.registerClientbound(ClientboundPackets1_14.ENTITY_POSITION_AND_ROTATION, relativeMoveHandler);
protocol.registerClientbound(ClientboundPackets1_14.SPAWN_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.VAR_INT, Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - Data
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
handler(getObjectTrackerHandler());
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int id = wrapper.get(Type.BYTE, 0);
int mappedId = newEntityId(id);
Entity1_13Types.EntityType entityType = Entity1_13Types.getTypeFromId(mappedId, false);
Entity1_13Types.ObjectType objectType;
if (entityType.isOrHasParent(Entity1_13Types.EntityType.MINECART_ABSTRACT)) {
objectType = Entity1_13Types.ObjectType.MINECART;
int data = 0;
switch (entityType) {
case CHEST_MINECART:
data = 1;
break;
case FURNACE_MINECART:
data = 2;
break;
case TNT_MINECART:
data = 3;
break;
case SPAWNER_MINECART:
data = 4;
break;
case HOPPER_MINECART:
data = 5;
break;
case COMMAND_BLOCK_MINECART:
data = 6;
break;
}
if (data != 0)
wrapper.set(Type.INT, 0, data);
} else {
objectType = Entity1_13Types.ObjectType.fromEntityType(entityType).orElse(null);
}
if (objectType == null) return;
wrapper.set(Type.BYTE, 0, (byte) objectType.getId());
int data = wrapper.get(Type.INT, 0);
if (objectType == Entity1_13Types.ObjectType.FALLING_BLOCK) {
int blockState = wrapper.get(Type.INT, 0);
int combined = protocol.getMappingData().getNewBlockStateId(blockState);
wrapper.set(Type.INT, 0, combined);
} else if (entityType.isOrHasParent(Entity1_13Types.EntityType.ABSTRACT_ARROW)) {
wrapper.set(Type.INT, 0, data + 1);
}
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.SPAWN_MOB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Entity UUID
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Yaw
map(Type.BYTE); // 7 - Pitch
map(Type.BYTE); // 8 - Head Pitch
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
map(Types1_14.METADATA_LIST, Types1_13_2.METADATA_LIST); // 12 - Metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int type = wrapper.get(Type.VAR_INT, 1);
EntityType entityType = Entity1_14Types.getTypeFromId(type);
addTrackedEntity(wrapper, wrapper.get(Type.VAR_INT, 0), entityType);
int oldId = newEntityId(type);
if (oldId == -1) {
EntityData entityData = entityDataForType(entityType);
if (entityData == null) {
ViaBackwards.getPlatform().getLogger().warning("Could not find 1.13.2 entity type for 1.14 entity type " + type + "/" + entityType);
wrapper.cancel();
} else {
wrapper.set(Type.VAR_INT, 1, entityData.replacementId());
}
} else {
wrapper.set(Type.VAR_INT, 1, oldId);
}
}
});
// Handle entity type & metadata
handler(getMobSpawnRewriter(Types1_13_2.METADATA_LIST));
}
});
protocol.registerClientbound(ClientboundPackets1_14.SPAWN_EXPERIENCE_ORB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.DOUBLE); // Needs to be mapped for the position cache
map(Type.DOUBLE);
map(Type.DOUBLE);
handler(wrapper -> addTrackedEntity(wrapper, wrapper.get(Type.VAR_INT, 0), Entity1_14Types.EXPERIENCE_ORB));
}
});
protocol.registerClientbound(ClientboundPackets1_14.SPAWN_GLOBAL_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.BYTE);
map(Type.DOUBLE); // Needs to be mapped for the position cache
map(Type.DOUBLE);
map(Type.DOUBLE);
handler(wrapper -> addTrackedEntity(wrapper, wrapper.get(Type.VAR_INT, 0), Entity1_14Types.LIGHTNING_BOLT));
}
});
protocol.registerClientbound(ClientboundPackets1_14.SPAWN_PAINTING, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.UUID);
map(Type.VAR_INT);
map(Type.POSITION1_14, Type.POSITION);
map(Type.BYTE);
// Track entity
handler(wrapper -> addTrackedEntity(wrapper, wrapper.get(Type.VAR_INT, 0), Entity1_14Types.PAINTING));
}
});
protocol.registerClientbound(ClientboundPackets1_14.SPAWN_PLAYER, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Player UUID
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Types1_14.METADATA_LIST, Types1_13_2.METADATA_LIST); // 7 - Metadata
handler(getTrackerAndMetaHandler(Types1_13_2.METADATA_LIST, Entity1_14Types.PLAYER));
handler(wrapper -> positionHandler.cacheEntityPosition(wrapper, true, false));
}
});
registerRemoveEntities(ClientboundPackets1_14.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_14.ENTITY_METADATA, Types1_14.METADATA_LIST, Types1_13_2.METADATA_LIST);
protocol.registerClientbound(ClientboundPackets1_14.JOIN_GAME, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Entity ID
map(Type.UNSIGNED_BYTE); // 1 - Gamemode
map(Type.INT); // 2 - Dimension
handler(getTrackerHandler(Entity1_14Types.PLAYER, Type.INT));
handler(getDimensionHandler(1));
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.write(Type.UNSIGNED_BYTE, (short) 0);
wrapper.passthrough(Type.UNSIGNED_BYTE); // Max Players
wrapper.passthrough(Type.STRING); // Level Type
wrapper.read(Type.VAR_INT); // Read View Distance
//TODO Track client position
// Manually add position storage
/*int entitiyId = wrapper.get(Type.INT, 0);
StoredEntityData storedEntity = protocol.getEntityRewriter().tracker(wrapper.user()).entityData(entitiyId);
storedEntity.put(new EntityPositionStorage1_14());*/
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_14.RESPAWN, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // 0 - Dimension ID
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
int dimensionId = wrapper.get(Type.INT, 0);
clientWorld.setEnvironment(dimensionId);
wrapper.write(Type.UNSIGNED_BYTE, (short) 0); // Difficulty
wrapper.user().get(ChunkLightStorage.class).clear();
}
});
}
});
}
@Override
protected void registerRewrites() {
mapTypes(Entity1_14Types.values(), Entity1_13Types.EntityType.class);
mapEntityTypeWithData(Entity1_14Types.CAT, Entity1_14Types.OCELOT).jsonName();
mapEntityTypeWithData(Entity1_14Types.TRADER_LLAMA, Entity1_14Types.LLAMA).jsonName();
mapEntityTypeWithData(Entity1_14Types.FOX, Entity1_14Types.WOLF).jsonName();
mapEntityTypeWithData(Entity1_14Types.PANDA, Entity1_14Types.POLAR_BEAR).jsonName();
mapEntityTypeWithData(Entity1_14Types.PILLAGER, Entity1_14Types.VILLAGER).jsonName();
mapEntityTypeWithData(Entity1_14Types.WANDERING_TRADER, Entity1_14Types.VILLAGER).jsonName();
mapEntityTypeWithData(Entity1_14Types.RAVAGER, Entity1_14Types.COW).jsonName();
filter().handler((event, meta) -> {
int typeId = meta.metaType().typeId();
if (typeId <= 15) {
meta.setMetaType(Types1_13_2.META_TYPES.byId(typeId));
}
MetaType type = meta.metaType();
if (type == Types1_13_2.META_TYPES.itemType) {
Item item = (Item) meta.getValue();
meta.setValue(protocol.getItemRewriter().handleItemToClient(item));
} else if (type == Types1_13_2.META_TYPES.blockStateType) {
int blockstate = (Integer) meta.getValue();
meta.setValue(protocol.getMappingData().getNewBlockStateId(blockstate));
}
});
filter().type(Entity1_14Types.PILLAGER).cancel(15);
filter().type(Entity1_14Types.FOX).cancel(15);
filter().type(Entity1_14Types.FOX).cancel(16);
filter().type(Entity1_14Types.FOX).cancel(17);
filter().type(Entity1_14Types.FOX).cancel(18);
filter().type(Entity1_14Types.PANDA).cancel(15);
filter().type(Entity1_14Types.PANDA).cancel(16);
filter().type(Entity1_14Types.PANDA).cancel(17);
filter().type(Entity1_14Types.PANDA).cancel(18);
filter().type(Entity1_14Types.PANDA).cancel(19);
filter().type(Entity1_14Types.PANDA).cancel(20);
filter().type(Entity1_14Types.CAT).cancel(18);
filter().type(Entity1_14Types.CAT).cancel(19);
filter().type(Entity1_14Types.CAT).cancel(20);
filter().handler((event, meta) -> {
EntityType type = event.entityType();
if (type == null) return;
if (type.isOrHasParent(Entity1_14Types.ABSTRACT_ILLAGER_BASE) || type == Entity1_14Types.RAVAGER || type == Entity1_14Types.WITCH) {
int index = event.index();
if (index == 14) {
event.cancel();
} else if (index > 14) {
event.setIndex(index - 1);
}
}
});
filter().type(Entity1_14Types.AREA_EFFECT_CLOUD).index(10).handler((event, meta) -> {
rewriteParticle((Particle) meta.getValue());
});
filter().type(Entity1_14Types.FIREWORK_ROCKET).index(8).handler((event, meta) -> {
meta.setMetaType(Types1_13_2.META_TYPES.varIntType);
Integer value = (Integer) meta.getValue();
if (value == null) {
meta.setValue(0);
}
});
filter().filterFamily(Entity1_14Types.ABSTRACT_ARROW).removeIndex(9);
filter().type(Entity1_14Types.VILLAGER).cancel(15); // Head shake timer
MetaHandler villagerDataHandler = (event, meta) -> {
VillagerData villagerData = (VillagerData) meta.getValue();
meta.setTypeAndValue(Types1_13_2.META_TYPES.varIntType, villagerDataToProfession(villagerData));
if (meta.id() == 16) {
event.setIndex(15); // decreased by 2 again in one of the following handlers
}
};
filter().type(Entity1_14Types.ZOMBIE_VILLAGER).index(18).handler(villagerDataHandler);
filter().type(Entity1_14Types.VILLAGER).index(16).handler(villagerDataHandler);
// Holding arms up - from bitfield into own boolean
filter().filterFamily(Entity1_14Types.ABSTRACT_SKELETON).index(13).handler((event, meta) -> {
byte value = (byte) meta.getValue();
if ((value & 4) != 0) {
event.createExtraMeta(new Metadata(14, Types1_13_2.META_TYPES.booleanType, true));
}
});
filter().filterFamily(Entity1_14Types.ZOMBIE).index(13).handler((event, meta) -> {
byte value = (byte) meta.getValue();
if ((value & 4) != 0) {
event.createExtraMeta(new Metadata(16, Types1_13_2.META_TYPES.booleanType, true));
}
});
filter().filterFamily(Entity1_14Types.ZOMBIE).addIndex(16);
// Remove bed location
filter().filterFamily(Entity1_14Types.LIVINGENTITY).handler((event, meta) -> {
int index = event.index();
if (index == 12) {
Position position = (Position) meta.getValue();
if (position != null) {
// Use bed
PacketWrapper wrapper = PacketWrapper.create(ClientboundPackets1_13.USE_BED, null, event.user());
wrapper.write(Type.VAR_INT, event.entityId());
wrapper.write(Type.POSITION, position);
try {
wrapper.scheduleSend(Protocol1_13_2To1_14.class);
} catch (Exception ex) {
ex.printStackTrace();
}
}
event.cancel();
} else if (index > 12) {
event.setIndex(index - 1);
}
});
// Something
filter().removeIndex(6);
filter().type(Entity1_14Types.OCELOT).index(13).handler((event, meta) -> {
event.setIndex(15);
meta.setTypeAndValue(Types1_13_2.META_TYPES.varIntType, 0);
});
filter().type(Entity1_14Types.CAT).handler((event, meta) -> {
if (event.index() == 15) {
meta.setValue(1);
} else if (event.index() == 13) {
meta.setValue((byte) ((byte) meta.getValue() & 0x4));
}
});
}
public int villagerDataToProfession(VillagerData data) {
switch (data.getProfession()) {
case 1: // Armorer
case 10: // Mason
case 13: // Toolsmith
case 14: // Weaponsmith
return 3; // Blacksmith
case 2: // Butcher
case 8: // Leatherworker
return 4; // Butcher
case 3: // Cartographer
case 9: // Librarian
return 1; // Librarian
case 4: // Cleric
return 2; // Priest
case 5: // Farmer
case 6: // Fisherman
case 7: // Fletcher
case 12: // Shepherd
return 0; // Farmer
case 0: // None
case 11: // Nitwit
default:
return 5; // Nitwit
}
}
@Override
public EntityType typeFromId(int typeId) {
return Entity1_14Types.getTypeFromId(typeId);
}
}
@@ -1,138 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_2to1_14.packets;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
public class PlayerPackets1_14 extends RewriterBase<Protocol1_13_2To1_14> {
public PlayerPackets1_14(Protocol1_13_2To1_14 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_14.SERVER_DIFFICULTY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE);
map(Type.BOOLEAN, Type.NOTHING); // Locked
}
});
protocol.registerClientbound(ClientboundPackets1_14.OPEN_SIGN_EDITOR, new PacketRemapper() { // c
@Override
public void registerMap() {
map(Type.POSITION1_14, Type.POSITION);
}
});
protocol.registerServerbound(ServerboundPackets1_13.QUERY_BLOCK_NBT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.POSITION, Type.POSITION1_14);
}
});
protocol.registerServerbound(ServerboundPackets1_13.PLAYER_DIGGING, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Action
map(Type.POSITION, Type.POSITION1_14); // Position
}
});
protocol.registerServerbound(ServerboundPackets1_13.RECIPE_BOOK_DATA, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int type = wrapper.get(Type.VAR_INT, 0);
if (type == 0) {
wrapper.passthrough(Type.STRING);
} else if (type == 1) {
wrapper.passthrough(Type.BOOLEAN); // Crafting Recipe Book Open
wrapper.passthrough(Type.BOOLEAN); // Crafting Recipe Filter Active
wrapper.passthrough(Type.BOOLEAN); // Smelting Recipe Book Open
wrapper.passthrough(Type.BOOLEAN); // Smelting Recipe Filter Active
// Blast furnace/smoker data
wrapper.write(Type.BOOLEAN, false);
wrapper.write(Type.BOOLEAN, false);
wrapper.write(Type.BOOLEAN, false);
wrapper.write(Type.BOOLEAN, false);
}
}
});
}
});
protocol.registerServerbound(ServerboundPackets1_13.UPDATE_COMMAND_BLOCK, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION, Type.POSITION1_14);
}
});
protocol.registerServerbound(ServerboundPackets1_13.UPDATE_STRUCTURE_BLOCK, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION, Type.POSITION1_14);
}
});
protocol.registerServerbound(ServerboundPackets1_13.UPDATE_SIGN, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION, Type.POSITION1_14);
}
});
protocol.registerServerbound(ServerboundPackets1_13.PLAYER_BLOCK_PLACEMENT, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
Position position = wrapper.read(Type.POSITION);
int face = wrapper.read(Type.VAR_INT);
int hand = wrapper.read(Type.VAR_INT);
float x = wrapper.read(Type.FLOAT);
float y = wrapper.read(Type.FLOAT);
float z = wrapper.read(Type.FLOAT);
wrapper.write(Type.VAR_INT, hand);
wrapper.write(Type.POSITION1_14, position);
wrapper.write(Type.VAR_INT, face);
wrapper.write(Type.FLOAT, x);
wrapper.write(Type.FLOAT, y);
wrapper.write(Type.FLOAT, z);
wrapper.write(Type.BOOLEAN, false); // Inside block
}
});
}
});
}
}
@@ -1,85 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13_2to1_14.packets;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viabackwards.protocol.protocol1_13_2to1_14.storage.EntityPositionStorage1_14;
import com.viaversion.viaversion.api.data.entity.StoredEntityData;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14;
public class SoundPackets1_14 extends RewriterBase<Protocol1_13_2To1_14> {
public SoundPackets1_14(Protocol1_13_2To1_14 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
SoundRewriter soundRewriter = new SoundRewriter(protocol);
soundRewriter.registerSound(ClientboundPackets1_14.SOUND);
soundRewriter.registerNamedSound(ClientboundPackets1_14.NAMED_SOUND);
soundRewriter.registerStopSound(ClientboundPackets1_14.STOP_SOUND);
// Entity Sound Effect
protocol.registerClientbound(ClientboundPackets1_14.ENTITY_SOUND, null, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
wrapper.cancel();
int soundId = wrapper.read(Type.VAR_INT);
int newId = protocol.getMappingData().getSoundMappings().getNewId(soundId);
if (newId == -1) return;
int category = wrapper.read(Type.VAR_INT);
int entityId = wrapper.read(Type.VAR_INT);
StoredEntityData storedEntity = wrapper.user().getEntityTracker(protocol.getClass()).entityData(entityId);
EntityPositionStorage1_14 entityStorage;
if (storedEntity == null || (entityStorage = storedEntity.get(EntityPositionStorage1_14.class)) == null) {
ViaBackwards.getPlatform().getLogger().warning("Untracked entity with id " + entityId);
return;
}
float volume = wrapper.read(Type.FLOAT);
float pitch = wrapper.read(Type.FLOAT);
int x = (int) (entityStorage.getX() * 8D);
int y = (int) (entityStorage.getY() * 8D);
int z = (int) (entityStorage.getZ() * 8D);
PacketWrapper soundPacket = wrapper.create(ClientboundPackets1_13.SOUND);
soundPacket.write(Type.VAR_INT, newId);
soundPacket.write(Type.VAR_INT, category);
soundPacket.write(Type.INT, x);
soundPacket.write(Type.INT, y);
soundPacket.write(Type.INT, z);
soundPacket.write(Type.FLOAT, volume);
soundPacket.write(Type.FLOAT, pitch);
soundPacket.send(Protocol1_13_2To1_14.class);
});
}
});
}
}
@@ -1,252 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13to1_13_1;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_13to1_13_1.data.CommandRewriter1_13_1;
import com.viaversion.viabackwards.protocol.protocol1_13to1_13_1.packets.EntityPackets1_13_1;
import com.viaversion.viabackwards.protocol.protocol1_13to1_13_1.packets.InventoryPackets1_13_1;
import com.viaversion.viabackwards.protocol.protocol1_13to1_13_1.packets.WorldPackets1_13_1;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_13Types;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.libs.gson.JsonElement;
import com.viaversion.viaversion.libs.gson.JsonObject;
import com.viaversion.viaversion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ChatRewriter;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
public class Protocol1_13To1_13_1 extends BackwardsProtocol<ClientboundPackets1_13, ClientboundPackets1_13, ServerboundPackets1_13, ServerboundPackets1_13> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.13.2", "1.13", Protocol1_13_1To1_13.class, true);
private final EntityRewriter entityRewriter = new EntityPackets1_13_1(this);
private final ItemRewriter itemRewriter = new InventoryPackets1_13_1(this);
public Protocol1_13To1_13_1() {
super(ClientboundPackets1_13.class, ClientboundPackets1_13.class, ServerboundPackets1_13.class, ServerboundPackets1_13.class);
}
@Override
protected void registerPackets() {
executeAsyncAfterLoaded(Protocol1_13_1To1_13.class, MAPPINGS::load);
entityRewriter.register();
itemRewriter.register();
WorldPackets1_13_1.register(this);
TranslatableRewriter translatableRewriter = new TranslatableRewriter(this);
translatableRewriter.registerChatMessage(ClientboundPackets1_13.CHAT_MESSAGE);
translatableRewriter.registerCombatEvent(ClientboundPackets1_13.COMBAT_EVENT);
translatableRewriter.registerDisconnect(ClientboundPackets1_13.DISCONNECT);
translatableRewriter.registerTabList(ClientboundPackets1_13.TAB_LIST);
translatableRewriter.registerTitle(ClientboundPackets1_13.TITLE);
translatableRewriter.registerPing();
new CommandRewriter1_13_1(this).registerDeclareCommands(ClientboundPackets1_13.DECLARE_COMMANDS);
registerServerbound(ServerboundPackets1_13.TAB_COMPLETE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT);
map(Type.STRING, new ValueTransformer<String, String>(Type.STRING) {
@Override
public String transform(PacketWrapper wrapper, String inputValue) {
// 1.13 starts sending slash at start, so we remove it for compatibility
return !inputValue.startsWith("/") ? "/" + inputValue : inputValue;
}
});
}
});
registerServerbound(ServerboundPackets1_13.EDIT_BOOK, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.FLAT_ITEM);
map(Type.BOOLEAN);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
itemRewriter.handleItemToServer(wrapper.get(Type.FLAT_ITEM, 0));
wrapper.write(Type.VAR_INT, 0);
}
});
}
});
registerClientbound(ClientboundPackets1_13.OPEN_WINDOW, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UNSIGNED_BYTE); // Id
map(Type.STRING); // Window Type
handler(wrapper -> {
JsonElement title = wrapper.passthrough(Type.COMPONENT);
translatableRewriter.processText(title);
if (ViaBackwards.getConfig().fix1_13FormattedInventoryTitle()) {
if (title.isJsonObject() && title.getAsJsonObject().size() == 1
&& title.getAsJsonObject().has("translate")) {
// Hotfix simple translatable components from being converted to legacy text
return;
}
// https://bugs.mojang.com/browse/MC-124543
JsonObject legacyComponent = new JsonObject();
legacyComponent.addProperty("text", ChatRewriter.jsonToLegacyText(title.toString()));
wrapper.set(Type.COMPONENT, 0, legacyComponent);
}
});
}
});
registerClientbound(ClientboundPackets1_13.TAB_COMPLETE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // Transaction id
map(Type.VAR_INT); // Start
map(Type.VAR_INT); // Length
map(Type.VAR_INT); // Count
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int start = wrapper.get(Type.VAR_INT, 1);
wrapper.set(Type.VAR_INT, 1, start - 1); // Offset by +1 to take into account / at beginning
// Passthrough suggestions
int count = wrapper.get(Type.VAR_INT, 3);
for (int i = 0; i < count; i++) {
wrapper.passthrough(Type.STRING);
boolean hasTooltip = wrapper.passthrough(Type.BOOLEAN);
if (hasTooltip) {
wrapper.passthrough(Type.STRING); // JSON Tooltip
}
}
}
});
}
});
registerClientbound(ClientboundPackets1_13.BOSSBAR, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.UUID);
map(Type.VAR_INT);
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int action = wrapper.get(Type.VAR_INT, 0);
if (action == 0 || action == 3) {
translatableRewriter.processText(wrapper.passthrough(Type.COMPONENT));
if (action == 0) {
wrapper.passthrough(Type.FLOAT);
wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.VAR_INT);
short flags = wrapper.read(Type.UNSIGNED_BYTE);
if ((flags & 0x04) != 0) flags |= 0x02;
wrapper.write(Type.UNSIGNED_BYTE, flags);
}
}
}
});
}
});
registerClientbound(ClientboundPackets1_13.ADVANCEMENTS, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.BOOLEAN); // Reset/clear
int size = wrapper.passthrough(Type.VAR_INT); // Mapping size
for (int i = 0; i < size; i++) {
wrapper.passthrough(Type.STRING); // Identifier
// Parent
if (wrapper.passthrough(Type.BOOLEAN))
wrapper.passthrough(Type.STRING);
// Display data
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.COMPONENT); // Title
wrapper.passthrough(Type.COMPONENT); // Description
Item icon = wrapper.passthrough(Type.FLAT_ITEM);
itemRewriter.handleItemToClient(icon);
wrapper.passthrough(Type.VAR_INT); // Frame type
int flags = wrapper.passthrough(Type.INT); // Flags
if ((flags & 1) != 0)
wrapper.passthrough(Type.STRING); // Background texture
wrapper.passthrough(Type.FLOAT); // X
wrapper.passthrough(Type.FLOAT); // Y
}
wrapper.passthrough(Type.STRING_ARRAY); // Criteria
int arrayLength = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < arrayLength; array++) {
wrapper.passthrough(Type.STRING_ARRAY); // String array
}
}
}
});
}
});
new TagRewriter(this).register(ClientboundPackets1_13.TAGS, RegistryType.ITEM);
new StatisticsRewriter(this).register(ClientboundPackets1_13.STATISTICS);
}
@Override
public void init(UserConnection user) {
user.addEntityTracker(getClass(), new EntityTrackerBase(user, Entity1_13Types.EntityType.PLAYER));
if (!user.has(ClientWorld.class)) {
user.put(new ClientWorld(user));
}
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityRewriter getEntityRewriter() {
return entityRewriter;
}
@Override
public ItemRewriter getItemRewriter() {
return itemRewriter;
}
}
@@ -1,179 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13to1_13_1.packets;
import com.viaversion.viabackwards.ViaBackwards;
import com.viaversion.viabackwards.api.rewriters.LegacyEntityRewriter;
import com.viaversion.viabackwards.protocol.protocol1_13to1_13_1.Protocol1_13To1_13_1;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_13Types;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import java.util.List;
public class EntityPackets1_13_1 extends LegacyEntityRewriter<Protocol1_13To1_13_1> {
public EntityPackets1_13_1(Protocol1_13To1_13_1 protocol) {
super(protocol);
}
@Override
protected void registerPackets() {
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_ENTITY, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity id
map(Type.UUID); // 1 - UUID
map(Type.BYTE); // 2 - Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Pitch
map(Type.BYTE); // 7 - Yaw
map(Type.INT); // 8 - Data
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
int entityId = wrapper.get(Type.VAR_INT, 0);
byte type = wrapper.get(Type.BYTE, 0);
Entity1_13Types.EntityType entType = Entity1_13Types.getTypeFromId(type, true);
if (entType == null) {
ViaBackwards.getPlatform().getLogger().warning("Could not find 1.13 entity type " + type);
return;
}
// Rewrite falling block
if (entType.is(Entity1_13Types.EntityType.FALLING_BLOCK)) {
int data = wrapper.get(Type.INT, 0);
wrapper.set(Type.INT, 0, protocol.getMappingData().getNewBlockStateId(data));
}
// Track Entity
tracker(wrapper.user()).addEntity(entityId, entType);
}
});
}
});
registerTracker(ClientboundPackets1_13.SPAWN_EXPERIENCE_ORB, Entity1_13Types.EntityType.EXPERIENCE_ORB);
registerTracker(ClientboundPackets1_13.SPAWN_GLOBAL_ENTITY, Entity1_13Types.EntityType.LIGHTNING_BOLT);
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_MOB, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Entity UUID
map(Type.VAR_INT); // 2 - Entity Type
map(Type.DOUBLE); // 3 - X
map(Type.DOUBLE); // 4 - Y
map(Type.DOUBLE); // 5 - Z
map(Type.BYTE); // 6 - Yaw
map(Type.BYTE); // 7 - Pitch
map(Type.BYTE); // 8 - Head Pitch
map(Type.SHORT); // 9 - Velocity X
map(Type.SHORT); // 10 - Velocity Y
map(Type.SHORT); // 11 - Velocity Z
map(Types1_13.METADATA_LIST); // 12 - Metadata
// Track Entity
handler(getTrackerHandler());
// Rewrite Metadata
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
List<Metadata> metadata = wrapper.get(Types1_13.METADATA_LIST, 0);
handleMetadata(wrapper.get(Type.VAR_INT, 0), metadata, wrapper.user());
}
});
}
});
protocol.registerClientbound(ClientboundPackets1_13.SPAWN_PLAYER, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.VAR_INT); // 0 - Entity ID
map(Type.UUID); // 1 - Player UUID
map(Type.DOUBLE); // 2 - X
map(Type.DOUBLE); // 3 - Y
map(Type.DOUBLE); // 4 - Z
map(Type.BYTE); // 5 - Yaw
map(Type.BYTE); // 6 - Pitch
map(Types1_13.METADATA_LIST); // 7 - Metadata
handler(getTrackerAndMetaHandler(Types1_13.METADATA_LIST, Entity1_13Types.EntityType.PLAYER));
}
});
registerTracker(ClientboundPackets1_13.SPAWN_PAINTING, Entity1_13Types.EntityType.PAINTING);
registerJoinGame(ClientboundPackets1_13.JOIN_GAME, Entity1_13Types.EntityType.PLAYER);
registerRespawn(ClientboundPackets1_13.RESPAWN);
registerRemoveEntities(ClientboundPackets1_13.DESTROY_ENTITIES);
registerMetadataRewriter(ClientboundPackets1_13.ENTITY_METADATA, Types1_13.METADATA_LIST);
}
@Override
protected void registerRewrites() {
// Rewrite items & blocks
filter().handler((event, meta) -> {
if (meta.metaType() == Types1_13.META_TYPES.itemType) {
protocol.getItemRewriter().handleItemToClient((Item) meta.getValue());
} else if (meta.metaType() == Types1_13.META_TYPES.blockStateType) {
// Convert to new block id
int data = (int) meta.getValue();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
} else if (meta.metaType() == Types1_13.META_TYPES.particleType) {
rewriteParticle((Particle) meta.getValue());
}
});
// Remove shooter UUID
filter().filterFamily(Entity1_13Types.EntityType.ABSTRACT_ARROW).cancel(7);
// Move colors to old position
filter().type(Entity1_13Types.EntityType.SPECTRAL_ARROW).index(8).toIndex(7);
// Move loyalty level to old position
filter().type(Entity1_13Types.EntityType.TRIDENT).index(8).toIndex(7);
// Rewrite Minecart blocks
filter().filterFamily(Entity1_13Types.EntityType.MINECART_ABSTRACT).index(9).handler((event, meta) -> {
int data = (int) meta.getValue();
meta.setValue(protocol.getMappingData().getNewBlockStateId(data));
});
}
@Override
public EntityType typeFromId(int typeId) {
return Entity1_13Types.getTypeFromId(typeId, false);
}
@Override
protected EntityType getObjectTypeFromId(final int typeId) {
return Entity1_13Types.getTypeFromId(typeId, true);
}
}
@@ -1,84 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2021 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.protocol1_13to1_13_1.packets;
import com.viaversion.viabackwards.protocol.protocol1_13to1_13_1.Protocol1_13To1_13_1;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketRemapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ServerboundPackets1_13;
import com.viaversion.viaversion.rewriter.ItemRewriter;
public class InventoryPackets1_13_1 extends ItemRewriter<Protocol1_13To1_13_1> {
public InventoryPackets1_13_1(Protocol1_13To1_13_1 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
registerSetCooldown(ClientboundPackets1_13.COOLDOWN);
registerWindowItems(ClientboundPackets1_13.WINDOW_ITEMS, Type.FLAT_ITEM_ARRAY);
registerSetSlot(ClientboundPackets1_13.SET_SLOT, Type.FLAT_ITEM);
protocol.registerClientbound(ClientboundPackets1_13.PLUGIN_MESSAGE, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
String channel = wrapper.passthrough(Type.STRING);
if (channel.equals("minecraft:trader_list")) {
wrapper.passthrough(Type.INT); //Passthrough Window ID
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
//Input Item
Item input = wrapper.passthrough(Type.FLAT_ITEM);
handleItemToClient(input);
//Output Item
Item output = wrapper.passthrough(Type.FLAT_ITEM);
handleItemToClient(output);
boolean secondItem = wrapper.passthrough(Type.BOOLEAN); //Has second item
if (secondItem) {
//Second Item
Item second = wrapper.passthrough(Type.FLAT_ITEM);
handleItemToClient(second);
}
wrapper.passthrough(Type.BOOLEAN); //Trade disabled
wrapper.passthrough(Type.INT); //Number of tools uses
wrapper.passthrough(Type.INT); //Maximum number of trade uses
}
}
}
});
}
});
registerEntityEquipment(ClientboundPackets1_13.ENTITY_EQUIPMENT, Type.FLAT_ITEM);
registerClickWindow(ServerboundPackets1_13.CLICK_WINDOW, Type.FLAT_ITEM);
registerCreativeInvAction(ServerboundPackets1_13.CREATIVE_INVENTORY_ACTION, Type.FLAT_ITEM);
registerSpawnParticle(ClientboundPackets1_13.SPAWN_PARTICLE, Type.FLAT_ITEM, Type.FLOAT);
}
}
Loaded 100 of 358 files, more files were not shown because too many files have changed in this diff. Show more