Compare commits

...
408 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
363 changed files with 24923 additions and 34145 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
+9 -11
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-22.04
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
- 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: 11
java-version: 17
check-latest: true
- name: Build with Gradle
run: ./gradlew build
- uses: actions/upload-artifact@v3
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
+1 -1
View File
@@ -1,6 +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-2022 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="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>
+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/KpLsMHj.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.2")
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", "META-INF/sponge_plugins.json", "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.5.1"
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-2022 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,52 +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 onServerLoaded() {
if (isOutdatedPostLoad()) {
disable();
return;
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();
}
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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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,13 @@
package com.viaversion.viabackwards;
import com.viaversion.viaversion.util.Config;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
public class ViaBackwardsConfig extends Config implements com.viaversion.viabackwards.api.ViaBackwardsConfig {
@@ -35,15 +34,15 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
private boolean alwaysShowOriginalMobName;
private boolean fix1_13FormattedInventoryTitles;
private boolean handlePingsAsInvAcknowledgements;
private Map<String, String> chatTypeFormats;
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();
}
@@ -54,7 +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);
chatTypeFormats = get("chat-types-1_19_1", Map.class, new HashMap<String, String>());
suppressEmulationWarnings = getBoolean("suppress-emulation-warnings", false);
}
@Override
@@ -88,8 +87,8 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
}
@Override
public @Nullable String chatTypeFormat(final String translationKey) {
return chatTypeFormats.get(translationKey);
public boolean suppressEmulationWarnings() {
return suppressEmulationWarnings;
}
@Override
@@ -97,6 +96,11 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback
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-2022 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-2022 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,9 +17,9 @@
*/
package com.viaversion.viabackwards.api;
import org.checkerframework.checker.nullness.qual.Nullable;
import com.viaversion.viaversion.api.configuration.Config;
public interface ViaBackwardsConfig {
public interface ViaBackwardsConfig extends Config {
/**
* Mimics name and level of a custom enchant through the item's lore.
@@ -42,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();
/**
@@ -51,7 +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();
@Nullable String chatTypeFormat(String translationKey);
/**
* 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-2022 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,54 +21,63 @@ 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_18_2to1_19.Protocol1_18_2To1_19;
import com.viaversion.viabackwards.protocol.protocol1_18to1_18_2.Protocol1_18To1_18_2;
import com.viaversion.viabackwards.protocol.protocol1_19_1to1_19_3.Protocol1_19_1To1_19_3;
import com.viaversion.viabackwards.protocol.protocol1_19to1_19_1.Protocol1_19To1_19_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.5.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);
@@ -77,51 +86,61 @@ public interface ViaBackwardsPlatform {
return;
}
Via.getManager().getSubPlatforms().add(IMPL_VERSION);
Via.getManager().getSubPlatforms().add(VersionInfo.getImplementationVersion());
getLogger().info("Loading translations...");
TranslatableRewriter.loadTranslatables();
getLogger().info("Registering protocols...");
final ProtocolManager protocolManager = Via.getManager().getProtocolManager();
protocolManager.registerProtocol(new Protocol1_9_4To1_10(), ProtocolVersion.v1_9_3, ProtocolVersion.v1_10);
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_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_17_1To1_18(), ProtocolVersion.v1_17_1, ProtocolVersion.v1_18);
protocolManager.registerProtocol(new Protocol1_18To1_18_2(), ProtocolVersion.v1_18, ProtocolVersion.v1_18_2);
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_18_2To1_19(), ProtocolVersion.v1_18_2, ProtocolVersion.v1_19);
protocolManager.registerProtocol(new Protocol1_19To1_19_1(), ProtocolVersion.v1_19, ProtocolVersion.v1_19_1);
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_19_1To1_19_3(), ProtocolVersion.v1_19_1, ProtocolVersion.v1_19_3);
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);
}
/**
@@ -135,7 +154,7 @@ 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");
@@ -145,10 +164,6 @@ public interface ViaBackwardsPlatform {
return false;
}
default boolean isOutdatedPostLoad() {
return false;
}
/**
* Disable the plugin.
*/
@@ -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,172 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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 final 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 unmapped, JsonObject mapped) {
}
protected boolean shouldWarnOnMissing(String key) {
return !key.equals("blocks") && !key.equals("statistics") && !key.equals("entities");
}
@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) {
if (entityNames == null) {
ViaBackwards.getPlatform().getLogger().severe("No entity mappings found when requesting them for " + entityName);
new Exception().printStackTrace();
return null;
}
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-2022 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-2022 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,179 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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 org.checkerframework.checker.nullness.qual.Nullable;
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 @Nullable InputStream getResource(String name) {
return VBMappingDataLoader.class.getClassLoader().getResourceAsStream("assets/viabackwards/data/" + name);
}
public static JsonObject loadData(String name) {
try (InputStream stream = getResource(name)) {
if (stream == null) return null;
return GsonUtil.getGson().fromJson(new InputStreamReader(stream), 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> newIdentifierMap = MappingDataLoader.indexedObjectToMap(newMapping);
Object2IntMap<String> oldIdentifierMap = MappingDataLoader.indexedObjectToMap(oldMapping);
for (Map.Entry<String, JsonElement> entry : diffMapping.entrySet()) {
JsonObject object = entry.getValue().getAsJsonObject();
String mappedIdName = object.getAsJsonPrimitive("id").getAsString();
int mappedId = newIdentifierMap.getInt(mappedIdName);
if (mappedId == -1) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
ViaBackwards.getPlatform().getLogger().warning("No key for " + mappedIdName + " :( ");
}
continue;
}
int oldId = oldIdentifierMap.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 : oldIdentifierMap.object2IntEntrySet()) {
if (!newIdentifierMap.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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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,73 +20,98 @@ 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 PacketHandler getSpawnTrackerWithDataHandler1_19(EntityType fallingBlockType) {
return wrapper -> {
if (protocol.getMappingData() == null) {
return;
}
// Check against the UNMAPPED entity type
EntityType entityType = setOldEntityId(wrapper);
EntityType entityType = trackAndMapEntity(wrapper);
if (entityType == fallingBlockType) {
int blockState = wrapper.get(Type.VAR_INT, 2);
wrapper.set(Type.VAR_INT, 2, protocol.getMappingData().getNewBlockStateId(blockState));
int blockState = wrapper.get(Types.VAR_INT, 2);
wrapper.set(Types.VAR_INT, 2, protocol.getMappingData().getNewBlockStateId(blockState));
}
};
}
public void registerSpawnTracker(ClientboundPacketType packetType) {
protocol.registerClientbound(packetType, new PacketRemapper() {
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));
}
});
}
@@ -99,7 +124,7 @@ public abstract class EntityRewriter<T extends BackwardsProtocol> extends Entity
public PacketHandler worldTrackerHandlerByKey() {
return wrapper -> {
EntityTracker tracker = tracker(wrapper.user());
String world = wrapper.get(Type.STRING, 1);
String world = wrapper.get(Types.STRING, 1);
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
tracker.clearEntities();
tracker.trackClientEntity();
@@ -114,14 +139,14 @@ public abstract class EntityRewriter<T extends BackwardsProtocol> extends Entity
* @param wrapper packet wrapper
* @return unmapped (!) entity type
*/
protected EntityType setOldEntityId(PacketWrapper wrapper) throws Exception {
int typeId = wrapper.get(Type.VAR_INT, 1);
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-2022 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.Int2IntMapMappings;
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.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,15 +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;
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;
@@ -63,37 +65,61 @@ public abstract class EntityRewriterBase<T extends BackwardsProtocol> extends En
}
@Override
public void handleMetadata(int entityId, List<Metadata> metadataList, UserConnection connection) {
super.handleMetadata(entityId, metadataList, connection);
public void handleEntityData(int entityId, List<EntityData> entityDataList, UserConnection connection) {
final TrackedEntity entity = tracker(connection).entity(entityId);
final boolean initialMetadata = !(entity != null && entity.hasSentEntityData());
EntityType type = tracker(connection).entityType(entityId);
if (type == null) {
super.handleEntityData(entityId, entityDataList, connection);
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;
}
@@ -101,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);
}
@@ -109,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());
}
@@ -126,54 +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 = Int2IntMapMappings.of();
}
for (EntityType oldType : oldTypes) {
try {
E newType = Enum.valueOf(newTypeClass, oldType.name());
typeMappings.setNewId(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());
}
});
}
@@ -182,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) {
@@ -197,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,163 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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.api.protocol.packet.ClientboundPacketType;
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.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> {
protected ItemRewriter(T protocol) {
super(protocol, true);
}
@Override
public @Nullable Item handleItemToClient(@Nullable Item item) {
if (item == null) return null;
CompoundTag display = item.tag() != null ? item.tag().get("display") : null;
if (protocol.getTranslatableRewriter() != null && display != null) {
// Handle name and lore components
StringTag name = display.get("Name");
if (name != null) {
String newValue = protocol.getTranslatableRewriter().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 = protocol.getTranslatableRewriter().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;
}
@Override
public void registerAdvancements(ClientboundPacketType packetType, Type<Item> type) {
protocol.registerClientbound(packetType, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
wrapper.passthrough(Type.BOOLEAN); // Reset/clear
final 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)) {
final JsonElement title = wrapper.passthrough(Type.COMPONENT);
final JsonElement description = wrapper.passthrough(Type.COMPONENT);
final TranslatableRewriter translatableRewriter = protocol.getTranslatableRewriter();
if (translatableRewriter != null) {
translatableRewriter.processText(title);
translatableRewriter.processText(description);
}
handleItemToClient(wrapper.passthrough(type)); // 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
final int arrayLength = wrapper.passthrough(Type.VAR_INT);
for (int array = 0; array < arrayLength; array++) {
wrapper.passthrough(Type.STRING_ARRAY); // String array
}
}
});
}
});
}
}
@@ -1,108 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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,14 +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);
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();
}
@@ -69,23 +72,23 @@ 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();
@@ -93,34 +96,42 @@ public class SoundRewriter extends com.viaversion.viaversion.rewriter.SoundRewri
};
}
public PacketHandler get1_19_3SoundHandler() {
return wrapper -> {
final int soundId = wrapper.read(Type.VAR_INT);
if (soundId != 0) {
final int mappedId = idRewriter.rewrite(soundId - 1); // Normalize the id
if (mappedId == -1) {
wrapper.cancel();
return;
}
@Override
public void registerSound1_19_3(final C packetType) {
protocol.registerClientbound(packetType, getSoundHandler1_19_3());
}
wrapper.write(Type.VAR_INT, mappedId + 1);
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;
}
// Is followed by the resource loation
wrapper.write(Type.VAR_INT, 0);
String soundIdentifier = wrapper.read(Type.STRING);
final String mappedIdentifier = protocol.getMappingData().getMappedNamedSound(soundIdentifier);
if (mappedIdentifier != null) {
if (mappedIdentifier.isEmpty()) {
wrapper.cancel();
return;
}
soundIdentifier = mappedIdentifier;
final int mappedId = idRewriter.rewrite(soundEventHolder.id());
if (mappedId == -1) {
wrapper.cancel();
return;
}
wrapper.write(Type.STRING, soundIdentifier);
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-2022 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,119 +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.loadFromDataDir("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 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-2022 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-2022 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-2022 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).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-2022 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 / 16f;
}
};
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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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-2022 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.registerComponentPacket(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-2022 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,147 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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<>();
public BackwardsMappings() {
super("1.13", "1.12", Protocol1_13To1_12_2.class, true);
}
@Override
public void loadVBExtras(JsonObject unmapped, JsonObject mapped) {
enchantmentMappings = VBMappings.vbBuilder().warnOnMissing(false)
.unmapped(unmapped.getAsJsonArray("enchantments")).mapped(mapped.getAsJsonObject("legacy_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;
}
}
@@ -1,204 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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-2022 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,646 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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);
packetWrapper.passthrough(Type.OPTIONAL_STRING);
}
packetWrapper.passthrough(Type.VAR_INT);
packetWrapper.passthrough(Type.VAR_INT);
packetWrapper.passthrough(Type.OPTIONAL_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
packetWrapper.passthrough(Type.OPTIONAL_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,99 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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.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.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() {
handler(wrapper -> {
String sound = wrapper.read(Type.STRING);
String mappedSound = NamedSoundMapping.getOldId(sound);
if (mappedSound != null || (mappedSound = protocol.getMappingData().getMappedNamedSound(sound)) != null) {
wrapper.write(Type.STRING, mappedSound);
} else {
wrapper.write(Type.STRING, sound);
}
});
}
});
// 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,117 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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 com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag;
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 {
final Tag idTag = tag.get("id");
if (!(idTag instanceof StringTag)) {
return tag;
}
String id = (String) idTag.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-2022 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-2022 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-2022 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-2022 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,222 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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.viabackwards.protocol.protocol1_13_2to1_14.storage.DifficultyStorage;
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 final TranslatableRewriter translatableRewriter = new TranslatableRewriter(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.registerBossBar(ClientboundPackets1_14.BOSSBAR);
translatableRewriter.registerComponentPacket(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);
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));
}
user.put(new DifficultyStorage(user));
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityRewriter getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPackets1_14 getItemRewriter() {
return blockItemPackets;
}
@Override
public TranslatableRewriter getTranslatableRewriter() {
return translatableRewriter;
}
}
@@ -1,597 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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.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) {
super(protocol);
}
@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) {
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,530 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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.DifficultyStorage;
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(wrapper -> {
short difficulty = wrapper.user().get(DifficultyStorage.class).getDifficulty();
wrapper.write(Type.UNSIGNED_BYTE, difficulty);
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(wrapper -> {
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
int dimensionId = wrapper.get(Type.INT, 0);
clientWorld.setEnvironment(dimensionId);
short difficulty = wrapper.user().get(DifficultyStorage.class).getDifficulty();
wrapper.write(Type.UNSIGNED_BYTE, 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 = meta.value();
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);
}
});
// Pose
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));
}
});
filter().handler((event, meta) -> {
if (meta.metaType().typeId() > 15) {
throw new IllegalArgumentException("Unhandled metadata: " + meta);
}
});
}
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,143 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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.viabackwards.protocol.protocol1_13_2to1_14.storage.DifficultyStorage;
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
handler(wrapper -> {
byte difficulty = wrapper.get(Type.UNSIGNED_BYTE, 0).byteValue();
wrapper.user().get(DifficultyStorage.class).setDifficulty(difficulty);
});
}
});
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-2022 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-2022 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.registerComponentPacket(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-2022 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-2022 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);
}
}
@@ -1,104 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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.viaversion.api.minecraft.BlockFace;
import com.viaversion.viaversion.api.minecraft.Position;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.protocol.Protocol;
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.types.Chunk1_13Type;
import com.viaversion.viaversion.protocols.protocol1_9_3to1_9_1_2.storage.ClientWorld;
import com.viaversion.viaversion.rewriter.BlockRewriter;
public class WorldPackets1_13_1 {
public static void register(Protocol protocol) {
BlockRewriter blockRewriter = new BlockRewriter(protocol, Type.POSITION);
protocol.registerClientbound(ClientboundPackets1_13.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.passthrough(new Chunk1_13Type(clientWorld));
for (ChunkSection section : chunk.getSections()) {
if (section != null) {
for (int i = 0; i < section.getPaletteSize(); i++) {
section.setPaletteEntry(i, protocol.getMappingData().getNewBlockStateId(section.getPaletteEntry(i)));
}
}
}
}
});
}
});
blockRewriter.registerBlockAction(ClientboundPackets1_13.BLOCK_ACTION);
blockRewriter.registerBlockChange(ClientboundPackets1_13.BLOCK_CHANGE);
blockRewriter.registerMultiBlockChange(ClientboundPackets1_13.MULTI_BLOCK_CHANGE);
protocol.registerClientbound(ClientboundPackets1_13.EFFECT, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.INT); // Effect Id
map(Type.POSITION); // Location
map(Type.INT); // Data
handler(wrapper -> {
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));
} else if (id == 2000) { // Smoke
switch (data) {
case 0: // Down
case 1: // Up
Position pos = wrapper.get(Type.POSITION, 0);
BlockFace relative = data == 0 ? BlockFace.BOTTOM : BlockFace.TOP;
wrapper.set(Type.POSITION, 0, pos.getRelative(relative)); // Y Offset
wrapper.set(Type.INT, 1, 4); // Self
break;
case 2: // North
wrapper.set(Type.INT, 1, 1); // North
break;
case 3: // South
wrapper.set(Type.INT, 1, 7); // South
break;
case 4: // West
wrapper.set(Type.INT, 1, 3); // West
break;
case 5: // East
wrapper.set(Type.INT, 1, 5); // East
break;
}
}
});
}
});
}
}
@@ -1,97 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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_14_2to1_14_3;
import com.viaversion.viabackwards.api.BackwardsProtocol;
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_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ServerboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.data.RecipeRewriter1_14;
import com.viaversion.viaversion.rewriter.RecipeRewriter;
public class Protocol1_14_2To1_14_3 extends BackwardsProtocol<ClientboundPackets1_14, ClientboundPackets1_14, ServerboundPackets1_14, ServerboundPackets1_14> {
public Protocol1_14_2To1_14_3() {
super(ClientboundPackets1_14.class, ClientboundPackets1_14.class, ServerboundPackets1_14.class, ServerboundPackets1_14.class);
}
@Override
protected void registerPackets() {
registerClientbound(ClientboundPackets1_14.TRADE_LIST, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.VAR_INT);
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
wrapper.passthrough(Type.FLAT_VAR_INT_ITEM);
wrapper.passthrough(Type.FLAT_VAR_INT_ITEM);
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.FLAT_VAR_INT_ITEM);
}
wrapper.passthrough(Type.BOOLEAN);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.FLOAT);
}
wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.VAR_INT);
wrapper.passthrough(Type.BOOLEAN);
wrapper.read(Type.BOOLEAN);
}
});
}
});
RecipeRewriter recipeHandler = new RecipeRewriter1_14(this);
registerClientbound(ClientboundPackets1_14.DECLARE_RECIPES, new PacketRemapper() {
@Override
public void registerMap() {
handler(wrapper -> {
int size = wrapper.passthrough(Type.VAR_INT);
int deleted = 0;
for (int i = 0; i < size; i++) {
String fullType = wrapper.read(Type.STRING);
String type = fullType.replace("minecraft:", "");
String id = wrapper.read(Type.STRING); // id
if (type.equals("crafting_special_repairitem")) {
deleted++;
continue;
}
wrapper.write(Type.STRING, fullType);
wrapper.write(Type.STRING, id);
recipeHandler.handle(wrapper, type);
}
wrapper.set(Type.VAR_INT, 0, size - deleted);
});
}
});
}
}
@@ -1,79 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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_14_3to1_14_4;
import com.viaversion.viabackwards.api.BackwardsProtocol;
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_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ServerboundPackets1_14;
public class Protocol1_14_3To1_14_4 extends BackwardsProtocol<ClientboundPackets1_14, ClientboundPackets1_14, ServerboundPackets1_14, ServerboundPackets1_14> {
public Protocol1_14_3To1_14_4() {
super(ClientboundPackets1_14.class, ClientboundPackets1_14.class, ServerboundPackets1_14.class, ServerboundPackets1_14.class);
}
@Override
protected void registerPackets() {
// Acknowledge Player Digging - added in pre4
registerClientbound(ClientboundPackets1_14.ACKNOWLEDGE_PLAYER_DIGGING, ClientboundPackets1_14.BLOCK_CHANGE, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.POSITION1_14);
map(Type.VAR_INT);
handler(wrapper -> {
int status = wrapper.read(Type.VAR_INT);
boolean allGood = wrapper.read(Type.BOOLEAN);
if (allGood && status == 0) {
wrapper.cancel();
}
});
}
});
registerClientbound(ClientboundPackets1_14.TRADE_LIST, new PacketRemapper() {
@Override
public void registerMap() {
handler(new PacketHandler() {
@Override
public void handle(PacketWrapper wrapper) throws Exception {
wrapper.passthrough(Type.VAR_INT);
int size = wrapper.passthrough(Type.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
wrapper.passthrough(Type.FLAT_VAR_INT_ITEM);
wrapper.passthrough(Type.FLAT_VAR_INT_ITEM);
if (wrapper.passthrough(Type.BOOLEAN)) {
wrapper.passthrough(Type.FLAT_VAR_INT_ITEM);
}
wrapper.passthrough(Type.BOOLEAN);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.INT);
wrapper.passthrough(Type.FLOAT);
wrapper.read(Type.INT); // demand value added in pre-5
}
}
});
}
});
}
}
@@ -1,130 +0,0 @@
/*
* This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards
* Copyright (C) 2016-2022 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_14_4to1_15;
import com.viaversion.viabackwards.api.BackwardsProtocol;
import com.viaversion.viabackwards.api.data.BackwardsMappings;
import com.viaversion.viabackwards.api.rewriters.SoundRewriter;
import com.viaversion.viabackwards.api.rewriters.TranslatableRewriter;
import com.viaversion.viabackwards.protocol.protocol1_14_4to1_15.data.ImmediateRespawn;
import com.viaversion.viabackwards.protocol.protocol1_14_4to1_15.packets.BlockItemPackets1_15;
import com.viaversion.viabackwards.protocol.protocol1_14_4to1_15.packets.EntityPackets1_15;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.Entity1_15Types;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
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_14to1_13_2.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ServerboundPackets1_14;
import com.viaversion.viaversion.protocols.protocol1_15to1_14_4.ClientboundPackets1_15;
import com.viaversion.viaversion.protocols.protocol1_15to1_14_4.Protocol1_15To1_14_4;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
public class Protocol1_14_4To1_15 extends BackwardsProtocol<ClientboundPackets1_15, ClientboundPackets1_14, ServerboundPackets1_14, ServerboundPackets1_14> {
public static final BackwardsMappings MAPPINGS = new BackwardsMappings("1.15", "1.14", Protocol1_15To1_14_4.class, true);
private final EntityRewriter entityRewriter = new EntityPackets1_15(this);
private final TranslatableRewriter translatableRewriter = new TranslatableRewriter(this);
private BlockItemPackets1_15 blockItemPackets;
public Protocol1_14_4To1_15() {
super(ClientboundPackets1_15.class, ClientboundPackets1_14.class, ServerboundPackets1_14.class, ServerboundPackets1_14.class);
}
@Override
protected void registerPackets() {
executeAsyncAfterLoaded(Protocol1_15To1_14_4.class, MAPPINGS::load);
translatableRewriter.registerBossBar(ClientboundPackets1_15.BOSSBAR);
translatableRewriter.registerComponentPacket(ClientboundPackets1_15.CHAT_MESSAGE);
translatableRewriter.registerCombatEvent(ClientboundPackets1_15.COMBAT_EVENT);
translatableRewriter.registerDisconnect(ClientboundPackets1_15.DISCONNECT);
translatableRewriter.registerOpenWindow(ClientboundPackets1_15.OPEN_WINDOW);
translatableRewriter.registerTabList(ClientboundPackets1_15.TAB_LIST);
translatableRewriter.registerTitle(ClientboundPackets1_15.TITLE);
translatableRewriter.registerPing();
(blockItemPackets = new BlockItemPackets1_15(this)).register();
entityRewriter.register();
SoundRewriter soundRewriter = new SoundRewriter(this);
soundRewriter.registerSound(ClientboundPackets1_15.SOUND);
soundRewriter.registerSound(ClientboundPackets1_15.ENTITY_SOUND);
soundRewriter.registerNamedSound(ClientboundPackets1_15.NAMED_SOUND);
soundRewriter.registerStopSound(ClientboundPackets1_15.STOP_SOUND);
// Explosion - manually send an explosion sound
registerClientbound(ClientboundPackets1_15.EXPLOSION, new PacketRemapper() {
@Override
public void registerMap() {
map(Type.FLOAT); // x
map(Type.FLOAT); // y
map(Type.FLOAT); // z
handler(wrapper -> {
PacketWrapper soundPacket = wrapper.create(ClientboundPackets1_14.SOUND);
soundPacket.write(Type.VAR_INT, 243); // entity.generic.explode
soundPacket.write(Type.VAR_INT, 4); // blocks category
soundPacket.write(Type.INT, toEffectCoordinate(wrapper.get(Type.FLOAT, 0))); // x
soundPacket.write(Type.INT, toEffectCoordinate(wrapper.get(Type.FLOAT, 1))); // y
soundPacket.write(Type.INT, toEffectCoordinate(wrapper.get(Type.FLOAT, 2))); // z
soundPacket.write(Type.FLOAT, 4F); // volume
soundPacket.write(Type.FLOAT, 1F); // pitch - usually semi randomized by the server, but we don't really have to care about that
soundPacket.send(Protocol1_14_4To1_15.class);
});
}
private int toEffectCoordinate(float coordinate) {
return (int) (coordinate * 8);
}
});
new TagRewriter(this).register(ClientboundPackets1_15.TAGS, RegistryType.ENTITY);
new StatisticsRewriter(this).register(ClientboundPackets1_15.STATISTICS);
}
@Override
public void init(UserConnection user) {
user.put(new ImmediateRespawn());
user.addEntityTracker(getClass(), new EntityTrackerBase(user, Entity1_15Types.PLAYER));
}
@Override
public BackwardsMappings getMappingData() {
return MAPPINGS;
}
@Override
public EntityRewriter getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPackets1_15 getItemRewriter() {
return blockItemPackets;
}
@Override
public TranslatableRewriter getTranslatableRewriter() {
return translatableRewriter;
}
}
Loaded 100 of 363 files, more files were not shown because too many files have changed in this diff. Show more