Compare commits

...
176 Commits
Author SHA1 Message Date
Nassim Jahnke f464e8e287 4.1.0 Release 2021-11-29 21:17:20 +01:00
Nassim Jahnke bd5217acb4 Merge remote-tracking branch 'origin/master' into dev 2021-11-28 16:09:21 +01:00
RK_01 e0cf62825b Fixed 1.9.3 -> 1.9.1 chunk translation (#2740) 2021-11-28 16:08:02 +01:00
Nassim Jahnke 9ce356aff4 another one 2021-11-26 17:15:10 +01:00
Nassim Jahnke 60fa54dddc 1.18-rc2 2021-11-26 10:53:58 +01:00
Nassim Jahnke 99b457965b 1.18-rc1 2021-11-25 16:09:34 +01:00
Nassim Jahnke 1d1a330ef1 1.18 pre8 2021-11-24 16:41:42 +01:00
Nassim Jahnke 4e9910c20e 1.18-pre7 2021-11-23 18:09:09 +01:00
Nassim Jahnke 82f2958ac6 1.18-pre6 2021-11-22 18:41:49 +01:00
Nassim Jahnke 1afa441571 Fix possible NPE in 1.13 component rewriting 2021-11-21 21:02:06 +01:00
Nassim Jahnke d159047dc0 Add more debugging options 2021-11-21 11:43:55 +01:00
Nassim Jahnke 3a529d00ce Fix update light passthrough 2021-11-19 21:35:21 +01:00
Nassim Jahnke b14b2b86e8 1.18-pre5 2021-11-19 17:27:43 +01:00
Nassim Jahnke 9ab4319771 *this is wrong intensifies* 2021-11-19 10:20:30 +01:00
Nassim Jahnke 8de7a4c828 Improve ceillog2 method 2021-11-19 10:06:45 +01:00
Nassim Jahnke 782d7a2172 this is wrong 2021-11-18 11:38:31 +01:00
Nassim Jahnke 2e5f3e4d66 this is wrong 2021-11-18 11:32:53 +01:00
Nassim Jahnke 6a00bf099e Cache 1.17.1 light by default, add config option 2021-11-18 11:23:46 +01:00
Nassim Jahnke bc11bd4caf Set mappings default values to -1 2021-11-17 19:52:06 +01:00
Nassim Jahnke c133552d04 1.18-pre4 2021-11-17 19:28:44 +01:00
Nassim Jahnke 2065a83fa1 Update biomes highest bits 2021-11-17 18:02:54 +01:00
Nassim Jahnke 30ce0eaa45 1.18-pre3 2021-11-17 17:43:17 +01:00
Nassim Jahnke 8be1fc9340 Move MetaTypes methods up into abstract class 2021-11-17 11:13:14 +01:00
Nassim Jahnke 6a8aa497b0 1.18-pre2 2021-11-16 13:28:53 +01:00
Nassim Jahnke 390155e03b Make Mappings extendable 2021-11-16 13:15:27 +01:00
Nassim Jahnke 3051ddb6c0 Better Mappings builders
Allows for mappings between json arrays and objects without a billion different constructors, also now uses the proper size for 1.18 chunks
2021-11-15 21:49:02 +01:00
Nassim Jahnke 25d74632c2 Update Bungee version warning 2021-11-15 11:00:18 +01:00
Nassim Jahnke 2b77427d0b Remove unused 1.18 code 2021-11-14 09:45:25 +01:00
_tomcraft dfc77b6f84 Update BungeeCord support (#2731)
fixes #2730
2021-11-14 09:44:33 +01:00
_tomcraft 6bc7f911c3 Fix bed rewriting and fix inconsistencies in item rewrite (#2729) 2021-11-14 09:37:03 +01:00
Nassim Jahnke 718614f81f 1.18 Pre-1 2021-11-11 10:06:59 +01:00
Nassim Jahnke 8e1f3bb086 Update Gradle to 7.3, adventure to 4.9.3 2021-11-11 10:05:58 +01:00
Nassim Jahnke 3a87eb463a Fix 1.18 spawner entity 2021-11-10 17:31:52 +01:00
Nassim Jahnke a49c395486 Make changes in particles easier to handle 2021-11-10 11:35:44 +01:00
Nassim Jahnke ad7f782a1a Fix InformativeException NPE 2021-11-08 12:09:08 +01:00
Nassim Jahnke 3aa84b5a5a Fix particle 1.18 meta type 2021-11-06 15:19:24 +01:00
Nassim Jahnke 52457ea749 Fix unquoted string being parsed as double 2021-11-05 18:19:14 +01:00
Nassim Jahnke 8104b96b8c Fix premature snbt numeric parsing 2021-11-04 19:43:48 +01:00
Nassim Jahnke a7835650bf Make model customization type with previous handlers 2021-11-03 19:16:03 +01:00
Nassim Jahnke d326dadb5d 21w44a 2021-11-03 19:14:33 +01:00
Nassim Jahnke d9307dad0c Merge remote-tracking branch 'origin/master' into dev 2021-11-03 10:53:16 +01:00
RK_01 752735159c Fixed credits screen not showing on 1.8 servers (#2724) 2021-11-02 19:01:29 +01:00
Nassim Jahnke 7cc6eb2b66 Fix accidental float/double NaN parsing in snbt 2021-11-02 15:09:40 +01:00
Nassim Jahnke 0a19057606 Merge remote-tracking branch 'origin/master' into dev 2021-10-30 15:56:39 +02:00
RK_01 a49d73c4c6 Abstract 1.8 metadata type (#2720) 2021-10-30 15:56:24 +02:00
Nassim Jahnke 82ded0299c Merge remote-tracking branch 'origin/master' into dev 2021-10-29 17:57:47 +02:00
Nassim Jahnke ab7cd4955b Metadata type should be written as var int 2021-10-29 17:57:23 +02:00
Nassim Jahnke 95493f3bbe Minor optimization 2021-10-29 17:47:38 +02:00
Nassim Jahnke a8c6f6b783 21w43a 2021-10-27 18:43:09 +02:00
Nassim Jahnke 516f746061 Handle barrier/light particles in entity meta 2021-10-25 09:52:54 +02:00
Nassim Jahnke d8d65ea989 Merge remote-tracking branch 'origin/master' into dev 2021-10-23 09:58:22 +02:00
Nassim Jahnke d80735e248 Read player digging action as var int
Does not matter for small numbers, but properly reflects Vanilla's reading/writing type
2021-10-23 09:58:11 +02:00
Redned ff5ad2385c Fix recipe book glitch on <1.16.2 servers (#2715) 2021-10-23 09:30:03 +02:00
Nassim Jahnke 2f28b25af3 Add block marker id to ParticleMappings 2021-10-20 18:51:53 +02:00
Nassim Jahnke 02bf9501a9 Handle item and particle meta 2021-10-20 18:48:07 +02:00
Nassim Jahnke a6292988d5 21w42a
Screw entity meta particles
2021-10-20 17:58:50 +02:00
Nassim Jahnke 431f773b77 Merge remote-tracking branch 'origin/master' into dev 2021-10-20 13:52:34 +02:00
Nassim Jahnke bd2bd1cf32 Cancel global entity packet if not lightning 2021-10-20 13:51:49 +02:00
Nassim Jahnke f5d92bf74f Merge remote-tracking branch 'origin/master' into dev 2021-10-19 09:16:06 +02:00
Nassim Jahnke dbe8b6551a Readd flare
Issues were addressed in 2.0.0
2021-10-19 09:10:17 +02:00
Nassim Jahnke 027e132749 Merge remote-tracking branch 'origin/master' into dev 2021-10-16 13:26:06 +02:00
Nassim Jahnke 7e3a157fcf Revert flare usage for now
Caused some issues I have no time to investigate at the moment, but worrying enough to warrant a temporary removal
Closes ViaVersion/ViaBackwards#402
2021-10-16 13:25:56 +02:00
Nassim Jahnke 9cd1ebf576 21w41a 2021-10-13 18:05:52 +02:00
Nassim Jahnke 03f929163c Merge remote-tracking branch 'origin/master' into dev 2021-10-11 21:04:29 +02:00
Nassim Jahnke e7e1ee7a2b Update shadow 2021-10-11 21:03:18 +02:00
_tomcraft 3f229c4cb9 Minor improvements (#2709) 2021-10-11 21:00:32 +02:00
Gero b2e0fdeaf8 Don't cancel chunks with missing light data (#2711) 2021-10-09 14:08:07 +02:00
Nassim Jahnke 0b541befbc Merge remote-tracking branch 'origin/master' into dev 2021-10-08 17:29:16 +02:00
Nassim Jahnke fd9346d4da Use validated channel in getNewPluginChannelId
Fixes #2707
2021-10-08 17:29:05 +02:00
Nassim JahnkeandGerrygames e744214ad6 Fix biome palette writing
Co-authored-by: Gerrygames <gecam59@gmail.com>
2021-10-08 13:17:07 +02:00
Nassim Jahnke 3feff8e751 Fix remove in ChunkLightStorage 2021-10-08 10:05:50 +02:00
Nassim Jahnke a2acd261d8 Merge remote-tracking branch 'origin/master' into dev 2021-10-08 09:37:32 +02:00
Nassim Jahnke 36b8884d92 Fix leftover FU load factors 2021-10-08 09:37:04 +02:00
Nassim Jahnke c15d7b8882 Don't forget id comments 2021-10-07 16:46:10 +02:00
Nassim Jahnke 9f33a09e87 21w40a 2021-10-07 16:44:43 +02:00
Nassim Jahnke cc78180a6c Merge remote-tracking branch 'origin/master' into dev 2021-10-07 12:27:21 +02:00
Connor Hartley e5338688bb Replace use of concurrenthashmap in entity tracker and block storage (#2705) 2021-10-07 12:26:14 +02:00
Nassim Jahnke b19ec959b3 Merge remote-tracking branch 'origin/master' into dev 2021-10-05 14:21:31 +02:00
MrMicky 8b4a57985b Remove usage of sun.misc.Unsafe in BungeeViaInjector (#2698) 2021-10-05 14:20:18 +02:00
Nassim Jahnke 7fb4e4a095 Change GH actions dist to adoptium 2021-10-05 14:10:04 +02:00
Nassim Jahnke 1bc4fc211d Merge remote-tracking branch 'origin/master' into dev 2021-10-03 20:15:19 +02:00
Nassim Jahnke 0a4d08886d Update adventure 2021-10-03 20:14:12 +02:00
creeper123123321 0f5fa620d1 Translatable ender dragon/wither text (#2702) 2021-10-03 16:23:41 +02:00
Gero a0f26f1ca3 Fix channel name validation in 1.13 to 1.12.2 protocol (#2701)
Closes #2187
2021-10-03 12:12:49 +02:00
MrMicky e64a0fb62e Prevent kick when signing empty book (#2700) 2021-10-03 10:11:34 +02:00
Nassim Jahnke 69409d71d1 Run handitem cache every tick 2021-10-02 16:38:20 +02:00
Nassim Jahnke 68c63d20ed Fix reading of explicit int array entries
See https://github.com/KyoriPowered/adventure/pull/460
2021-10-02 11:27:18 +02:00
Nassim Jahnke 2afa3fd9de Merge remote-tracking branch 'origin/master' into dev 2021-10-01 22:46:37 +02:00
Myles 0bcaf3e422 Merge pull request #2695 from ViaVersion/legacy-injector-cleanup
Cleanup Bukkit/Sponge injectors
2021-10-01 15:38:03 +01:00
Nassim Jahnke 6e5992c168 Add docs to abstract LegacyViaInjector methods 2021-10-01 16:33:18 +02:00
Gero 02122f8ce6 Fix #2532 2021-10-01 15:35:04 +02:00
_tomcraft 39f7f70a32 Cancel arm animation if in an open inventory for 1.16+ (#2687) 2021-10-01 12:38:49 +02:00
Nassim Jahnke 427b0a68d0 Cleanup Bukkit/Sponge injectors 2021-10-01 12:17:55 +02:00
Nassim Jahnke 50f3a05fa5 21w39a (probably) 2021-09-29 20:16:31 +02:00
Nassim JahnkeandRK_01 a306c222d4 More NBTTagTest test cases
Co-authored-by: RK_01 <50594595+raphimc@users.noreply.github.com>
2021-09-25 15:43:55 +02:00
Nassim Jahnke 5bfee3339a Merge remote-tracking branch 'origin/master' into dev 2021-09-25 14:57:41 +02:00
Nassim Jahnke 2b9df69627 Fix trailing comma again, fix 'possiblyNumeric' DoubleTag parsing 2021-09-25 14:57:14 +02:00
Nassim Jahnke 4f1e92f309 Merge remote-tracking branch 'origin/master' into dev 2021-09-25 13:18:59 +02:00
Nassim Jahnke 88165088a9 Update adventure nbt i/o 2021-09-25 13:15:26 +02:00
Nassim Jahnke e38f76b8bc Definitely did not forget to update mappings 2021-09-24 14:39:38 +02:00
Nassim Jahnke 1f63fc7de1 21w38a 2021-09-23 17:23:14 +02:00
Nassim Jahnke 763a88fe97 Merge remote-tracking branch 'origin/master' into dev 2021-09-22 11:16:35 +02:00
Nassim Jahnke 12e2be40e8 Remove some old todos, don't send empty 1.14->1.15 meta packet 2021-09-22 11:15:36 +02:00
Nassim Jahnke 22379eda6f Add todo 2021-09-22 10:16:42 +02:00
Nassim Jahnke 4485af577d Merge remote-tracking branch 'origin/master' into dev 2021-09-21 11:02:40 +02:00
Nassim Jahnke 0fcfd78b62 Add more user friendly 'block-versions' option 2021-09-20 15:15:25 +02:00
Nassim Jahnke 4940ed66c1 Don't warn on superfluous bytes
Should be looked into, but not now™️
2021-09-16 18:17:44 +02:00
Nassim Jahnke 73093c0ff2 Read/write palette based on block/biome size variables 2021-09-16 18:12:33 +02:00
Nassim Jahnke c5e27b89af Don't read remaining bytes in 1.18 chunk type 2021-09-16 17:01:58 +02:00
Nassim Jahnke 111cd2fd46 Biome palettes entries can have 1 bit 2021-09-16 15:47:28 +02:00
Nassim Jahnke 5a90c8374c Fix named sound packets and old block entities 2021-09-16 15:41:14 +02:00
Nassim Jahnke 9ffa737a4d Implement BlockEntity sectionX/Z methods 2021-09-16 14:19:45 +02:00
Nassim Jahnke c565f2c9c7 Cleanup Palette interface and read/write 2021-09-16 13:03:31 +02:00
Nassim Jahnke eaa18f569a Write linear palette as map palette for now 2021-09-16 12:17:21 +02:00
Nassim Jahnke bfe6389377 Write biomes to palette 2021-09-16 11:35:05 +02:00
Nassim Jahnke f72412484a Map block entity ids, only biomes and something else left 2021-09-16 00:26:23 +02:00
Nassim Jahnke b4301adb3b WIP 21w37a 2021-09-15 23:00:14 +02:00
Levertion d67269c9fe Add support for setting a custom world name (#2672) 2021-09-15 10:52:11 +02:00
Nassim Jahnke c264e639d6 Clear entity data on world change in world tracker 2021-09-14 17:35:27 +02:00
Nassim Jahnke 32a84f24ef Nicer getters in Pair and Triple 2021-09-14 11:13:39 +02:00
Nassim Jahnke 68e4146f3b Deprecate cancelClientbound/Serverbound with new id parameter 2021-09-05 14:02:33 +02:00
Nassim Jahnke f4f7215a6a Fix disabled packet limiter check 2021-09-02 17:33:09 +02:00
Nassim Jahnke a0b19872f8 Disable VV packet limiter on 1.17.1+ Paper 2021-09-01 15:25:24 +02:00
Nassim Jahnke f2147179c2 Small fixes, add majorVersion method, nicer getter names in some classes
None of the deprecated methods will be removed anytime soon.
2021-08-28 22:15:28 +02:00
RK_01 e7a0b4cf04 Improve 1.8 -> 1.9 chunk translation and fix #2065 (#2669) 2021-08-28 10:02:27 +02:00
Nassim Jahnke 533572e8cd Add CREATE_FOG BossFlag 2021-08-27 19:29:07 +02:00
creeper123123321 257eea5b04 try to fix GoLilyPad servers (#2667)
Closes ViaVersion/ViaFabric#21
2021-08-25 14:55:43 +02:00
Jo0001 47af0d634f Fix typo in comment/javadocs (#2609) 2021-08-25 12:49:57 +02:00
kennytv 5e11d9d51f Update Gradle to 7.2 2021-08-17 13:37:51 +02:00
kennytv 7ffcff7a7b Fix 1.15->1.16 wolf anger 2021-08-14 10:37:21 +02:00
kennytv 9ee548b967 Fix 1.17 clients writing empty books
Fixes #2658
2021-08-11 15:11:56 +02:00
kennytv c9142223fd Gitignores don't have to be .gitignore'd 2021-08-02 17:59:12 +02:00
kennytv 2094397bca Allow bypassing of packet type restriction in Protocol, amend packet creator 2021-08-01 12:05:04 +02:00
kennytv b81109f512 Semi force packet types in PacketWrapper at creation and transformation 2021-07-31 15:08:45 +02:00
kennytv 874dbafe26 More packet sending API
Allows for easy packet sending from a specific version to or from any client version supported by Via.
For example, you can send packets in the 1.17.1 format to both client and server, and it will be transformed accordingly if executed on another server version or sent to a different client version.
2021-07-30 12:26:15 +02:00
kennytv 46ca469a4a Add author tag to constructed book nbt
Fixes #2640
2021-07-27 11:58:24 +02:00
Pierre Maurice Schwang 8fb51bf3b7 Update bug_report.yml (#2636) 2021-07-25 09:51:04 +02:00
creeper123123321 9874a9053a it's 2021 and we should use UTF 8 (#2633) 2021-07-23 21:31:25 +02:00
kennytv db87774426 Fix ProtocolSupport compat on 1.17
Fixes #2632

Thank you md_5, very cool
2021-07-23 10:15:59 +02:00
creeper123123321 d14db9396b Fix idle ticking in proxies (#2631) 2021-07-20 18:57:53 +02:00
kennytv d7966567e7 Lowercase gang 2021-07-07 20:43:27 +02:00
KennyTV b4f8024eef Fix 1.15->1.16 and 1.16.1->1.16.2 dropped items
Fixes #2610
2021-07-07 10:06:15 +02:00
KennyTV e70f230f39 Bump version to 4.0.2-SNAPSHOT 2021-07-07 09:59:49 +02:00
KennyTV b28f743306 4.0.1 Release 2021-07-06 10:31:03 +02:00
KennyTV 9f97a09942 1.17.1-rc2 2021-07-05 14:52:13 +02:00
KennyTV 4f7e655613 1.17.1-rc1 2021-07-01 19:58:34 +02:00
KennyTV a7d94c2f8f 1.17.1-pre3 2021-06-30 18:19:19 +02:00
KennyTV c2172821fd Merge remote-tracking branch 'origin/master' into dev 2021-06-29 18:12:36 +02:00
KennyTV 24393d4ef4 1.17.1-pre2 2021-06-29 18:11:51 +02:00
KennyTV 622ea91648 Ignore bad 1.8 wither meta
Fixes #2570
2021-06-22 11:28:09 +02:00
KennyTV aed1a63a77 Merge remote-tracking branch 'origin/master' into dev 2021-06-21 14:58:38 +02:00
LemonCaramel 14cd568e46 Add Resource pack prompt message option (1.17+) (#2544) 2021-06-21 14:55:49 +02:00
KennyTV 44d836e2e7 Clear entity trackers on server switch
Fixes #5930
2021-06-21 14:33:23 +02:00
_tomcraft f9af6947f7 Improve arm-swing cancel by resetting cursor item (#2528) 2021-06-20 22:50:37 +02:00
_tomcraft 8e1da82793 Use a more fork-proof approach to enable Paper block place patch (#2561) 2021-06-20 22:49:59 +02:00
KennyTV 860aca974b Read unsigned byte in set slot 2021-06-20 16:16:08 +02:00
KennyTV 6a66d7653f Fix writable book id 2021-06-20 16:16:07 +02:00
KennyTV d32a4541a9 1.17.1-pre1 2021-06-20 16:16:07 +02:00
KennyTV 26719169ee Fix 1.8 special inventory tracking 2021-06-20 16:15:48 +02:00
KennyTV eae145543e Fix 1.8 set slot write type
Fixes #2558
2021-06-19 15:35:43 +02:00
KennyTV 48f1300908 Read set slot inv id as unsigned byte for consistency 2021-06-18 16:59:34 +02:00
KennyTV 5cdaabeaec Handle particle id change in 1.16 metadata
Fixes #2551
2021-06-17 11:55:22 +02:00
KennyTV 40f87e9472 Update Gradle wrapper to 7.1 2021-06-16 09:12:23 +02:00
KennyTV 7f385d4762 Create concurrent hashmap with weak values with Guava
This could use Guava's Cache, but that's just the MapMaker but more
2021-06-15 09:59:23 +02:00
KennyTV 389c5adaa3 Half revert back to storing uuids in CommonBoss
Fixes #2547
2021-06-14 22:47:13 +02:00
KennyTV 7a82ded94b Fix Velocity compatibility (requires Velocity 3.0.0)
This finally removes the hacky reorder fix on Velocity; it added a few more events that could benefit us, but this is the most important right now.
2021-06-14 21:09:47 +02:00
Myles 86278e837a Fix 1.17 BungeeCord support 2021-06-14 19:46:25 +01:00
KennyTV 34a0499152 Update bug_report.yml 2021-06-14 10:59:01 +02:00
Myles 68ccc6634d Spigot 1.17 compatibility 2021-06-11 20:19:06 +01:00
Jo0001 317af7ebc5 Use the correct content-type header (#2527) 2021-06-10 22:15:14 +02:00
KennyTV 206368b777 Fix 1.12->1.13 entity tracking
Fixes #2526
2021-06-10 22:10:22 +02:00
KennyTV 204a81b0ea Add 1.17 to legacy api package ProtocolVersion 2021-06-10 10:50:07 +02:00
KennyTV b940ecab9c Fix meta warning 2021-06-10 08:42:52 +02:00
KennyTV 15cbc96697 Shorten metadata error message 2021-06-09 18:59:48 +02:00
KennyTV b5e5b46f77 Update adventure to 4.8.0 release 2021-06-08 19:07:09 +02:00
KennyTV 42b6a1378c Bump to 4.0.1-SNAPSHOT 2021-06-08 19:06:08 +02:00
288 changed files with 31824 additions and 3384 deletions

No files matched your search

+2 -1
View File
@@ -1,5 +1,6 @@
name: Bug Report
description: Report a bug or console error
labels: [Unconfirmed]
body:
- type: markdown
@@ -87,5 +88,5 @@ body:
required: true
- label: If applicable, I have included a paste (**not a screenshot**) of the error.
required: true
- label: I have tried a build from https://ci.viaversion.com/ and the issue still persists.
- label: I have tried the latest build(s) from https://ci.viaversion.com/ and the issue still persists.
required: true
+2 -2
View File
@@ -7,7 +7,7 @@ on: [push, pull_request]
jobs:
build:
# Only run on PRs if the source branch is on a different repo. We do not need run everything twice.
# Only run on PRs if the source branch is on a different repo. We do not need to run everything twice.
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-latest
@@ -18,7 +18,7 @@ jobs:
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
distribution: 'adopt'
distribution: 'temurin'
java-version: 11
- name: Build with Gradle
run: ./gradlew build
+2 -5
View File
@@ -106,8 +106,5 @@ nbactions.xml
nb-configuration.xml
.nb-gradle/
### Git ###
# Don't exclude the .gitignore itself
!.gitignore
### MacOS ###
.DS_Store
+1 -1
View File
@@ -8,7 +8,7 @@
Supported Versions:
![Table (https://i.imgur.com/uDM9HR8.png)](https://i.imgur.com/uDM9HR8.png)
![Table (https://i.imgur.com/uDM9HR8.png)](https://i.imgur.com/RRa5KnK.png)
On Paper you may also use ProtocolSupport, but ensure you have the right build for your server version.
@@ -79,6 +79,9 @@ public class ProtocolVersion {
public static final ProtocolVersion v1_16_2 = register(751, "1.16.2");
public static final ProtocolVersion v1_16_3 = register(753, "1.16.3");
public static final ProtocolVersion v1_16_4 = register(754, "1.16.4/5", new VersionRange("1.16", 4, 5));
public static final ProtocolVersion v1_17 = register(755, "1.17");
public static final ProtocolVersion v1_17_1 = register(756, "1.17.1");
public static final ProtocolVersion v1_18 = register(757, "1.18");
public static final ProtocolVersion unknown = register(-1, "UNKNOWN");
public static ProtocolVersion register(int version, String name) {
@@ -165,12 +168,12 @@ public class ProtocolVersion {
Preconditions.checkArgument(!versionWildcard || versionRange == null, "A version cannot be a wildcard and a range at the same time!");
if (versionRange != null) {
includedVersions = new LinkedHashSet<>();
for (int i = versionRange.getRangeFrom(); i <= versionRange.getRangeTo(); i++) {
for (int i = versionRange.rangeFrom(); i <= versionRange.rangeTo(); i++) {
if (i == 0) {
includedVersions.add(versionRange.getBaseVersion()); // Keep both the base version and with ".0" appended
includedVersions.add(versionRange.baseVersion()); // Keep both the base version and with ".0" appended
}
includedVersions.add(versionRange.getBaseVersion() + "." + i);
includedVersions.add(versionRange.baseVersion() + "." + i);
}
} else {
includedVersions = Collections.singleton(name);
+2
View File
@@ -13,6 +13,8 @@ dependencies {
targetConfiguration = "shadow"
}
api(libs.fastutil)
api(libs.flare)
api(libs.flareFastutil)
api(libs.openNBT)
api(libs.gson)
@@ -46,13 +46,25 @@ import java.util.UUID;
public interface ViaAPI<T> {
/**
* Returns the API version incremented with meaningful API changes.
* Returns the <b>major version</b> matching {@link #getVersion()}.
* It is highly advised to check against the major version and to disable/not initiate
* any hooks into ViaVersion if given and expected versions do not match.
*
* @return major plugin version
* @since 4.0.2
*/
default int majorVersion() {
return 4;
}
/**
* Returns an <b>internally based API version</b> incremented with meaningful API changes.
* This includes breaking changes to existing API and larger additions.
*
* @return API version incremented with meaningful API changes
*/
default int apiVersion() {
return 3;
return 10;
}
/**
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api;
import com.viaversion.viaversion.api.command.ViaVersionCommand;
import com.viaversion.viaversion.api.connection.ConnectionManager;
import com.viaversion.viaversion.api.debug.DebugHandler;
import com.viaversion.viaversion.api.platform.ViaInjector;
import com.viaversion.viaversion.api.platform.ViaPlatform;
import com.viaversion.viaversion.api.platform.ViaPlatformLoader;
@@ -88,14 +89,27 @@ public interface ViaManager {
*
* @return true if enabled
*/
boolean isDebug();
@Deprecated
default boolean isDebug() {
return debugHandler().enabled();
}
/**
* Sets the debug mode. If enabled, packets and other otherwise suppressed warnings will be logged.
*
* @param debug whether debug should be enabled
*/
void setDebug(boolean debug);
@Deprecated
default void setDebug(boolean debug) {
debugHandler().setEnabled(debug);
}
/**
* Returns the debug handler.
*
* @return debug handler
*/
DebugHandler debugHandler();
/**
* Returns a mutable set of self-added subplatform version strings.
@@ -22,6 +22,11 @@
*/
package com.viaversion.viaversion.api.configuration;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.WorldIdentifiers;
import com.viaversion.viaversion.api.protocol.version.BlockedProtocolVersions;
import it.unimi.dsi.fastutil.ints.IntSet;
public interface ViaVersionConfig {
@@ -229,6 +234,13 @@ public interface ViaVersionConfig {
*/
int getPistonReplacementId();
/**
* Fix 1.9+ clients not rendering the far away chunks
*
* @return true to fix chunk borders
*/
boolean isChunkBorderFix();
/**
* Force json transform
*
@@ -257,12 +269,23 @@ public interface ViaVersionConfig {
*/
boolean is1_12QuickMoveActionFix();
/**
* API to check for blocked protocol versions.
*
* @return blocked protocol versions
*/
BlockedProtocolVersions blockedProtocolVersions();
/**
* Get the blocked protocols
*
* @return An Integer list
* @deprecated use {@link #blockedProtocolVersions()}
*/
IntSet getBlockedProtocols();
@Deprecated/*(forRemoval = true)*/
default IntSet getBlockedProtocols() {
return blockedProtocolVersions().singleBlockedVersions();
}
/**
* Get the custom disconnect message
@@ -414,4 +437,22 @@ public interface ViaVersionConfig {
* @return true if enabled
*/
boolean isForcedUse1_17ResourcePack();
/**
* Get the message that is sent when a user displays a resource pack prompt.
*
* @return cached serialized component
*/
JsonElement get1_17ResourcePackPrompt();
/***
* Get the world names that should be returned for each Vanilla dimension.
* Note that this can be overriden per-user by using {@link UserConnection#put(StorableObject)} with
* a custom instance of {@link WorldIdentifiers} for the user's {@link UserConnection}.
*
* @return the global map from vanilla dimensions to world name
*/
WorldIdentifiers get1_16WorldNamesMap();
boolean cache1_17Light();
}
@@ -90,8 +90,8 @@ public interface UserConnection {
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
/**
* Clear all the stored objects.
* Used for bungee when switching servers.
* Clear stored objects and entity trackers.
* Used for Bungee when switching servers.
*/
void clearStoredObjects();
@@ -291,12 +291,26 @@ public interface UserConnection {
boolean isClientSide();
/**
* Returns whether {@link ViaVersionConfig#getBlockedProtocols()} should be checked for this connection.
* Returns whether {@link ViaVersionConfig#blockedProtocolVersions()} should be checked for this connection.
*
* @return whether blocked protocols should be applied
*/
boolean shouldApplyBlockProtocol();
/**
* Returns whether the packet limiter applies to this user.
*
* @return whether the packet limiter applies to this user
*/
boolean isPacketLimiterEnabled();
/**
* Sets the status of the packet limiter.
*
* @param packetLimiterEnabled whether the packet limiter should be enabled
*/
void setPacketLimiterEnabled(boolean packetLimiterEnabled);
/**
* Returns a newly generated uuid that will let a packet be passed through without
* transformig its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
@@ -29,79 +29,82 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Arrays;
public class IntArrayMappings implements Mappings {
protected final int[] oldToNew;
private final int[] oldToNew;
private final int mappedIds;
public IntArrayMappings(int[] oldToNew) {
protected IntArrayMappings(final int[] oldToNew, final int mappedIds) {
this.oldToNew = oldToNew;
this.mappedIds = mappedIds;
}
/**
* Maps old identifiers to the new ones.
* If an old value cannot be found in the new mappings, the diffmapping will be checked for the given entry.
*
* @param size set size of the underlying short array
* @param oldMapping mappings to map from
* @param newMapping mappings to map to
* @param diffMapping extra mappings that will be used/scanned when an entry cannot be found
*/
public static IntArrayMappings of(final int[] oldToNew, final int mappedIds) {
return new IntArrayMappings(oldToNew, mappedIds);
}
public static Builder<IntArrayMappings> builder() {
return Mappings.builder(IntArrayMappings::new);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(int[] oldToNew) {
this(oldToNew, -1);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(int size, JsonObject oldMapping, JsonObject newMapping, @Nullable JsonObject diffMapping) {
oldToNew = new int[size];
Arrays.fill(oldToNew, -1);
this.mappedIds = newMapping.size();
MappingDataLoader.mapIdentifiers(oldToNew, oldMapping, newMapping, diffMapping);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(JsonObject oldMapping, JsonObject newMapping, @Nullable JsonObject diffMapping) {
this(oldMapping.entrySet().size(), oldMapping, newMapping, diffMapping);
}
/**
* Maps old identifiers to the new ones.
*
* @param size set size of the underlying short array
* @param oldMapping mappings to map from
* @param newMapping mappings to map to
*/
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(int size, JsonObject oldMapping, JsonObject newMapping) {
oldToNew = new int[size];
Arrays.fill(oldToNew, -1);
mappedIds = -1;
MappingDataLoader.mapIdentifiers(oldToNew, oldMapping, newMapping);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(JsonObject oldMapping, JsonObject newMapping) {
this(oldMapping.entrySet().size(), oldMapping, newMapping);
}
/**
* Maps old identifiers to the new ones.
*
* @param size set size of the underlying short array
* @param oldMapping mappings to map from
* @param newMapping mappings to map to
* @param diffMapping extra mappings that will be used/scanned when an entry cannot be found
* @param warnOnMissing should "No key for x" be printed if there is no matching identifier
*/
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(int size, JsonArray oldMapping, JsonArray newMapping, JsonObject diffMapping, boolean warnOnMissing) {
oldToNew = new int[size];
Arrays.fill(oldToNew, -1);
mappedIds = -1;
MappingDataLoader.mapIdentifiers(oldToNew, oldMapping, newMapping, diffMapping, warnOnMissing);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(int size, JsonArray oldMapping, JsonArray newMapping, boolean warnOnMissing) {
this(size, oldMapping, newMapping, null, warnOnMissing);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(JsonArray oldMapping, JsonArray newMapping, boolean warnOnMissing) {
this(oldMapping.size(), oldMapping, newMapping, warnOnMissing);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(int size, JsonArray oldMapping, JsonArray newMapping) {
this(size, oldMapping, newMapping, true);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(JsonArray oldMapping, JsonArray newMapping, JsonObject diffMapping) {
this(oldMapping.size(), oldMapping, newMapping, diffMapping, true);
}
@Deprecated/*(forRemoval = true)*/
public IntArrayMappings(JsonArray oldMapping, JsonArray newMapping) {
this(oldMapping.size(), oldMapping, newMapping, true);
}
@@ -116,6 +119,16 @@ public class IntArrayMappings implements Mappings {
oldToNew[id] = newId;
}
@Override
public int size() {
return oldToNew.length;
}
@Override
public int mappedSize() {
return mappedIds;
}
public int[] getOldToNew() {
return oldToNew;
}
@@ -95,6 +95,8 @@ public interface MappingData {
@Nullable Mappings getBlockMappings();
@Nullable Mappings getBlockEntityMappings();
@Nullable Mappings getBlockStateMappings();
@Nullable Mappings getSoundMappings();
@@ -47,6 +47,7 @@ public class MappingDataBase implements MappingData {
protected ParticleMappings particleMappings;
protected Mappings blockMappings;
protected Mappings blockStateMappings;
protected Mappings blockEntityMappings;
protected Mappings soundMappings;
protected Mappings statisticsMappings;
protected Map<RegistryType, List<TagData>> tags;
@@ -71,6 +72,7 @@ public class MappingDataBase implements MappingData {
blockMappings = loadFromObject(oldMappings, newMappings, diffmapping, "blocks");
blockStateMappings = loadFromObject(oldMappings, newMappings, diffmapping, "blockstates");
blockEntityMappings = loadFromArray(oldMappings, newMappings, diffmapping, "blockentities");
soundMappings = loadFromArray(oldMappings, newMappings, diffmapping, "sounds");
statisticsMappings = loadFromArray(oldMappings, newMappings, diffmapping, "statistics");
@@ -83,16 +85,16 @@ public class MappingDataBase implements MappingData {
itemMappings = new Int2IntBiHashMap();
itemMappings.defaultReturnValue(-1);
MappingDataLoader.mapIdentifiers(itemMappings, oldMappings.getAsJsonObject("items"), newMappings.getAsJsonObject("items"),
diffmapping != null ? diffmapping.getAsJsonObject("items") : null);
diffmapping != null ? diffmapping.getAsJsonObject("items") : null, true);
}
if (diffmapping != null && diffmapping.has("tags")) {
this.tags = new EnumMap<>(RegistryType.class);
JsonObject tags = diffmapping.getAsJsonObject("tags");
if (tags.has(RegistryType.ITEM.getResourceLocation())) {
if (tags.has(RegistryType.ITEM.resourceLocation())) {
loadTags(RegistryType.ITEM, tags, MappingDataLoader.indexedObjectToMap(newMappings.getAsJsonObject("items")));
}
if (tags.has(RegistryType.BLOCK.getResourceLocation())) {
if (tags.has(RegistryType.BLOCK.resourceLocation())) {
loadTags(RegistryType.BLOCK, tags, MappingDataLoader.indexedObjectToMap(newMappings.getAsJsonObject("blocks")));
}
}
@@ -101,7 +103,7 @@ public class MappingDataBase implements MappingData {
}
private void loadTags(RegistryType type, JsonObject object, Object2IntMap<String> typeMapping) {
JsonObject tags = object.getAsJsonObject(type.getResourceLocation());
JsonObject tags = object.getAsJsonObject(type.resourceLocation());
List<TagData> tagsList = new ArrayList<>(tags.size());
for (Map.Entry<String, JsonElement> entry : tags.entrySet()) {
JsonArray array = entry.getValue().getAsJsonArray();
@@ -169,6 +171,11 @@ public class MappingDataBase implements MappingData {
return blockMappings;
}
@Override
public @Nullable Mappings getBlockEntityMappings() {
return blockEntityMappings;
}
@Override
public @Nullable Mappings getBlockStateMappings() {
return blockStateMappings;
@@ -188,14 +195,16 @@ public class MappingDataBase implements MappingData {
if (!oldMappings.has(key) || !newMappings.has(key)) return null;
JsonObject diff = diffMappings != null ? diffMappings.getAsJsonObject(key) : null;
return new IntArrayMappings(oldMappings.getAsJsonArray(key), newMappings.getAsJsonArray(key), diff);
return IntArrayMappings.builder().unmapped(oldMappings.getAsJsonArray(key))
.mapped(newMappings.getAsJsonArray(key)).diffMappings(diff).build();
}
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 new IntArrayMappings(oldMappings.getAsJsonObject(key), newMappings.getAsJsonObject(key), diff);
return IntArrayMappings.builder().unmapped(oldMappings.getAsJsonObject(key))
.mapped(newMappings.getAsJsonObject(key)).diffMappings(diff).build();
}
protected @Nullable JsonObject loadDiffFile() {
@@ -135,31 +135,36 @@ public class MappingDataLoader {
}
}
public static void mapIdentifiers(Int2IntBiMap output, JsonObject oldIdentifiers, JsonObject newIdentifiers, @Nullable JsonObject diffIdentifiers) {
public static void mapIdentifiers(Int2IntBiMap output, JsonObject oldIdentifiers, JsonObject newIdentifiers, @Nullable JsonObject diffIdentifiers, boolean warnOnMissing) {
Object2IntMap<String> newIdentifierMap = MappingDataLoader.indexedObjectToMap(newIdentifiers);
for (Map.Entry<String, JsonElement> entry : oldIdentifiers.entrySet()) {
int value = mapIdentifierEntry(entry, newIdentifierMap, diffIdentifiers);
int value = mapIdentifierEntry(entry, newIdentifierMap, diffIdentifiers, warnOnMissing);
if (value != -1) {
output.put(Integer.parseInt(entry.getKey()), value);
}
}
}
@Deprecated/*(forRemoval = true)*/
public static void mapIdentifiers(int[] output, JsonObject oldIdentifiers, JsonObject newIdentifiers) {
MappingDataLoader.mapIdentifiers(output, oldIdentifiers, newIdentifiers, null);
mapIdentifiers(output, oldIdentifiers, newIdentifiers, null);
}
public static void mapIdentifiers(int[] output, JsonObject oldIdentifiers, JsonObject newIdentifiers, @Nullable JsonObject diffIdentifiers) {
public static void mapIdentifiers(int[] output, JsonObject oldIdentifiers, JsonObject newIdentifiers, @Nullable JsonObject diffIdentifiers, boolean warnOnMissing) {
Object2IntMap<String> newIdentifierMap = MappingDataLoader.indexedObjectToMap(newIdentifiers);
for (Map.Entry<String, JsonElement> entry : oldIdentifiers.entrySet()) {
int value = mapIdentifierEntry(entry, newIdentifierMap, diffIdentifiers);
int value = mapIdentifierEntry(entry, newIdentifierMap, diffIdentifiers, warnOnMissing);
if (value != -1) {
output[Integer.parseInt(entry.getKey())] = value;
}
}
}
private static int mapIdentifierEntry(Map.Entry<String, JsonElement> entry, Object2IntMap newIdentifierMap, @Nullable JsonObject diffIdentifiers) {
public static void mapIdentifiers(int[] output, JsonObject oldIdentifiers, JsonObject newIdentifiers, @Nullable JsonObject diffIdentifiers) {
mapIdentifiers(output, oldIdentifiers, newIdentifiers, diffIdentifiers, true);
}
private static int mapIdentifierEntry(Map.Entry<String, JsonElement> entry, Object2IntMap newIdentifierMap, @Nullable JsonObject diffIdentifiers, boolean warnOnMissing) {
int value = newIdentifierMap.getInt(entry.getValue().getAsString());
if (value == -1) {
// Search in diff mappings
@@ -170,7 +175,7 @@ public class MappingDataLoader {
}
}
if (value == -1) {
if (!Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
if (warnOnMissing && !Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) {
Via.getPlatform().getLogger().warning("No key for " + entry.getValue() + " :( ");
}
return -1;
@@ -179,6 +184,7 @@ public class MappingDataLoader {
return value;
}
@Deprecated/*(forRemoval = true)*/
public static void mapIdentifiers(int[] output, JsonArray oldIdentifiers, JsonArray newIdentifiers, boolean warnOnMissing) {
mapIdentifiers(output, oldIdentifiers, newIdentifiers, null, warnOnMissing);
}
@@ -217,7 +223,7 @@ public class MappingDataLoader {
* @return map with indexes hashed by their id value
*/
public static Object2IntMap<String> indexedObjectToMap(JsonObject object) {
Object2IntMap<String> map = new Object2IntOpenHashMap<>(object.size(), 1F);
Object2IntMap<String> map = new Object2IntOpenHashMap<>(object.size(), .99F);
map.defaultReturnValue(-1);
for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
map.put(entry.getValue().getAsString(), Integer.parseInt(entry.getKey()));
@@ -232,7 +238,7 @@ public class MappingDataLoader {
* @return map with indexes hashed by their id value
*/
public static Object2IntMap<String> arrayToMap(JsonArray array) {
Object2IntMap<String> map = new Object2IntOpenHashMap<>(array.size(), 1F);
Object2IntMap<String> map = new Object2IntOpenHashMap<>(array.size(), .99F);
map.defaultReturnValue(-1);
for (int i = 0; i < array.size(); i++) {
map.put(array.get(i).getAsString(), i);
@@ -22,6 +22,12 @@
*/
package com.viaversion.viaversion.api.data;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import java.util.Arrays;
public interface Mappings {
/**
@@ -40,4 +46,137 @@ public interface Mappings {
* @throws IndexOutOfBoundsException if the unmapped id is invalid
*/
void setNewId(int id, int newId);
/**
* Returns amount of unmapped entries, being the size of the mapping.
*
* @return amount of unmapped entries
*/
int size();
/**
* Returns the amount of new ids total, even if it does not have a direct mapping.
* Returns -1 if unknown.
*
* @return amount of new ids, or -1 if unknown
*/
int mappedSize();
static <T extends Mappings> Builder<T> builder(final MappingsSupplier<T> supplier) {
return new Builder(supplier);
}
@FunctionalInterface
interface MappingsSupplier<T extends Mappings> {
T supply(int[] mappings, int mappedIds);
}
class Builder<T extends Mappings> {
protected final MappingsSupplier<T> supplier;
protected JsonElement unmapped;
protected JsonElement mapped;
protected JsonObject diffMappings;
protected int mappedSize = -1;
protected int size = -1;
protected boolean warnOnMissing = true;
protected Builder(final MappingsSupplier<T> supplier) {
this.supplier = supplier;
}
/**
* Sets a custom entry size different to the size of the unmapped collection.
*
* @param size custom entry size
* @return self
*/
public Builder<T> customEntrySize(final int size) {
this.size = size;
return this;
}
/**
* Sets a custom entry mapped ids count different to the size of the mapped collection.
*
* @param size custom mapped id count
* @return self
*/
public Builder<T> customMappedSize(final int size) {
this.mappedSize = size;
return this;
}
/**
* Sets whether warnings should be logged for missing mapped ids.
*
* @param warnOnMissing whether warnings should be logged for missing mapped ids
* @return self
*/
public Builder<T> warnOnMissing(final boolean warnOnMissing) {
this.warnOnMissing = warnOnMissing;
return this;
}
public Builder<T> unmapped(final JsonArray unmappedArray) {
this.unmapped = unmappedArray;
return this;
}
public Builder<T> unmapped(final JsonObject unmappedObject) {
this.unmapped = unmappedObject;
return this;
}
public Builder<T> mapped(final JsonArray mappedArray) {
this.mapped = mappedArray;
return this;
}
public Builder<T> mapped(final JsonObject mappedObject) {
this.mapped = mappedObject;
return this;
}
public Builder<T> diffMappings(final JsonObject diffMappings) {
this.diffMappings = diffMappings;
return this;
}
public T 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()) {
MappingDataLoader.mapIdentifiers(mappings, toJsonObject(unmapped.getAsJsonArray()), mapped.getAsJsonObject(), diffMappings, warnOnMissing);
} else {
MappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonArray(), mapped.getAsJsonArray(), diffMappings, warnOnMissing);
}
} else if (mapped.isJsonArray()) {
MappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonObject(), toJsonObject(mapped.getAsJsonArray()), diffMappings, warnOnMissing);
} else {
MappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonObject(), mapped.getAsJsonObject(), diffMappings, warnOnMissing);
}
return supplier.supply(mappings, mappedSize);
}
protected int size(final JsonElement element) {
return element.isJsonObject() ? element.getAsJsonObject().size() : element.getAsJsonArray().size();
}
protected JsonObject toJsonObject(final JsonArray array) {
final JsonObject object = new JsonObject();
for (int i = 0; i < array.size(); i++) {
final JsonElement element = array.get(i);
object.add(Integer.toString(i), element);
}
return object;
}
}
}
@@ -23,36 +23,71 @@
package com.viaversion.viaversion.api.data;
import com.google.gson.JsonArray;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
public class ParticleMappings {
private final Object2IntMap<String> stringToId;
private final Mappings mappings;
private final int blockId;
private final int fallingDustId;
private final int itemId;
private final IntList itemParticleIds = new IntArrayList(2);
private final IntList blockParticleIds = new IntArrayList(4);
public ParticleMappings(JsonArray oldMappings, Mappings mappings) {
this.mappings = mappings;
Object2IntMap<String> map = MappingDataLoader.arrayToMap(oldMappings);
blockId = map.getInt("block");
fallingDustId = map.getInt("falling_dust");
itemId = map.getInt("item");
stringToId = MappingDataLoader.arrayToMap(oldMappings);
stringToId.defaultReturnValue(-1);
addBlockParticle("block");
addBlockParticle("falling_dust");
addBlockParticle("block_marker");
addItemParticle("item");
}
/**
* Returns the unmapped integer id for the given identifier, or -1 if not found.
*
* @param identifier unmapped string identifier
* @return unmapped int id, or -1 if not found
*/
public int id(String identifier) {
return stringToId.getInt(identifier);
}
public Mappings getMappings() {
return mappings;
}
public boolean addItemParticle(final String identifier) {
final int id = id(identifier);
return id != -1 && itemParticleIds.add(id);
}
public boolean addBlockParticle(final String identifier) {
final int id = id(identifier);
return id != -1 && blockParticleIds.add(id);
}
public boolean isBlockParticle(final int id) {
return blockParticleIds.contains(id);
}
public boolean isItemParticle(final int id) {
return itemParticleIds.contains(id);
}
@Deprecated/*(forRemoval = true)*/
public int getBlockId() {
return blockId;
return id("block");
}
@Deprecated/*(forRemoval = true)*/
public int getFallingDustId() {
return fallingDustId;
return id("falling_dust");
}
@Deprecated/*(forRemoval = true)*/
public int getItemId() {
return itemId;
return id("item");
}
}
@@ -67,12 +67,18 @@ public interface EntityTracker {
*/
void removeEntity(int id);
/**
* Clears stored entity types and data.
*/
void clearEntities();
/**
* Returns the stored entity data if an entity with the id is tracked, else null.
* If no data has been initialized yet, it will be done and returned by this method.
*
* @param id entity id
* @return stored entity data if an entity with the id is tracked, else null
* @throws IllegalArgumentException if entitiy data storage has not been enabled via the implementation
*/
@Nullable StoredEntityData entityData(int id);
@@ -81,6 +87,7 @@ public interface EntityTracker {
*
* @param id entity id
* @return stored entity data if it has previously been initialized by {@link #entityData(int)}
* @throws IllegalArgumentException if entitiy data storage has not been enabled via the implementation
*/
@Nullable StoredEntityData entityDataIfPresent(int id);
@@ -99,8 +106,8 @@ public interface EntityTracker {
void setClientEntityId(int clientEntityId);
/**
* Returns the current world section height.
* Always 16 for sub 1.17 worlds.
* Returns the current world section height (block height / 16).
* This is always 16 for sub 1.17 worlds.
*
* @return current world section height
*/
@@ -126,4 +133,22 @@ public interface EntityTracker {
* @param currentMinY minimum y of the current world
*/
void setCurrentMinY(int currentMinY);
/**
* Returns the name of the world the player is currently in.
*
* @return world name of the current world
*/
@Nullable String currentWorld();
/**
* Sets the name of the world the player is currently in.
*
* @param currentWorld name of the current world
*/
void setCurrentWorld(String currentWorld);
int biomesSent();
void setBiomesSent(int biomesSent);
}
@@ -0,0 +1,85 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.debug;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
public interface DebugHandler {
/**
* Returns whether debug mode is enabled.
*
* @return whether debug mode is enabled
*/
boolean enabled();
/**
* Sets debug mode.
*
* @param enabled whether debug should be enabled
*/
void setEnabled(boolean enabled);
/**
* Adds a packet type name to the list of packet types to log.
*
* @param packetTypeName packet type name
*/
void addPacketTypeNameToLog(String packetTypeName);
/**
* Removes a packet type name from the list of packet types to log.
*
* @param packetTypeName packet type name
*/
boolean removePacketTypeNameToLog(String packetTypeName);
/**
* Resets packet type filters.
*/
void clearPacketTypesToLog();
/**
* Returns whether packets should be logged after being transformed.
* Set to true by default.
*
* @return whether packets should be logged after being transformed
*/
boolean logPostPacketTransform();
/**
* Sets whether packets should be logged after being transformed.
*
* @param logPostPacketTransform whether packets should be logged after being transformed
*/
void setLogPostPacketTransform(boolean logPostPacketTransform);
/**
* Returns whether the given packet should be logged.
* If no specific packet type has been added, all packet types will be logged.
*
* @param wrapper packet wrapper
* @return whether the packet should be logged
*/
boolean shouldLog(PacketWrapper wrapper);
}
@@ -25,7 +25,8 @@ package com.viaversion.viaversion.api.legacy.bossbar;
public enum BossFlag {
DARKEN_SKY(1),
PLAY_BOSS_MUSIC(2);
PLAY_BOSS_MUSIC(2),
CREATE_FOG(4);
private final int id;
@@ -58,7 +58,7 @@ public class BlockChangeRecord1_16_2 implements BlockChangeRecord {
@Override
public short getY(int chunkSectionY) {
Preconditions.checkArgument(chunkSectionY >= 0 && chunkSectionY < 16, "Invalid chunkSectionY: " + chunkSectionY);
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: " + chunkSectionY);
return (short) ((chunkSectionY << 4) + sectionY);
}
@@ -33,6 +33,8 @@ public enum BlockFace {
TOP((byte) 0, (byte) 1, (byte) 0, EnumAxis.Y),
BOTTOM((byte) 0, (byte) -1, (byte) 0, EnumAxis.Y);
public static final BlockFace[] HORIZONTAL = new BlockFace[]{NORTH, SOUTH, EAST, WEST};
private static final Map<BlockFace, BlockFace> opposites = new HashMap<>();
static {
@@ -60,18 +62,38 @@ public enum BlockFace {
return opposites.get(this);
}
public byte modX() {
return modX;
}
public byte modY() {
return modY;
}
public byte modZ() {
return modZ;
}
public EnumAxis axis() {
return axis;
}
@Deprecated/*(forRemoval = true)*/
public byte getModX() {
return modX;
}
@Deprecated/*(forRemoval = true)*/
public byte getModY() {
return modY;
}
@Deprecated/*(forRemoval = true)*/
public byte getModZ() {
return modZ;
}
@Deprecated/*(forRemoval = true)*/
public EnumAxis getAxis() {
return axis;
}
@@ -34,6 +34,11 @@ public enum Environment {
this.id = id;
}
public int id() {
return id;
}
@Deprecated/*(forRemoval = true)*/
public int getId() {
return id;
}
@@ -33,14 +33,29 @@ public class EulerAngle {
this.z = z;
}
public float x() {
return x;
}
public float y() {
return y;
}
public float z() {
return z;
}
@Deprecated/*(forRemoval = true)*/
public float getX() {
return x;
}
@Deprecated/*(forRemoval = true)*/
public float getY() {
return y;
}
@Deprecated/*(forRemoval = true)*/
public float getZ() {
return z;
}
@@ -33,28 +33,43 @@ public class Position {
this.z = z;
}
@Deprecated/*(forRemoval=true)*/
public Position(int x, short y, int z) {
this.x = x;
this.y = y;
this.z = z;
this(x, (int) y, z);
}
@Deprecated/*(forRemoval=true)*/
public Position(Position toCopy) {
this(toCopy.getX(), toCopy.getY(), toCopy.getZ());
this(toCopy.x(), toCopy.y(), toCopy.z());
}
public Position getRelative(BlockFace face) {
return new Position(x + face.getModX(), (short) (y + face.getModY()), z + face.getModZ());
return new Position(x + face.modX(), (short) (y + face.modY()), z + face.modZ());
}
public int x() {
return x;
}
public int y() {
return y;
}
public int z() {
return z;
}
@Deprecated/*(forRemoval=true)*/
public int getX() {
return x;
}
@Deprecated/*(forRemoval=true)*/
public int getY() {
return y;
}
@Deprecated/*(forRemoval=true)*/
public int getZ() {
return z;
}
@@ -58,7 +58,12 @@ public enum RegistryType {
this.resourceLocation = resourceLocation;
}
@Deprecated/*(forRemoval = true)*/
public String getResourceLocation() {
return resourceLocation;
}
public String resourceLocation() {
return resourceLocation;
}
}
@@ -33,26 +33,44 @@ public class Vector {
this.blockZ = blockZ;
}
public int blockX() {
return blockX;
}
public int blockY() {
return blockY;
}
public int blockZ() {
return blockZ;
}
@Deprecated/*(forRemoval=true)*/
public int getBlockX() {
return blockX;
}
public void setBlockX(int blockX) {
this.blockX = blockX;
}
@Deprecated/*(forRemoval=true)*/
public int getBlockY() {
return blockY;
}
public void setBlockY(int blockY) {
this.blockY = blockY;
}
@Deprecated/*(forRemoval=true)*/
public int getBlockZ() {
return blockZ;
}
@Deprecated/*(forRemoval=true)*/
public void setBlockX(int blockX) {
this.blockX = blockX;
}
@Deprecated/*(forRemoval=true)*/
public void setBlockY(int blockY) {
this.blockY = blockY;
}
@Deprecated/*(forRemoval=true)*/
public void setBlockZ(int blockZ) {
this.blockZ = blockZ;
}
@@ -33,14 +33,29 @@ public class VillagerData {
this.level = level;
}
public int type() {
return type;
}
public int profession() {
return profession;
}
public int level() {
return level;
}
@Deprecated/*(forRemoval=true)*/
public int getType() {
return type;
}
@Deprecated/*(forRemoval=true)*/
public int getProfession() {
return profession;
}
@Deprecated/*(forRemoval=true)*/
public int getLevel() {
return level;
}
@@ -0,0 +1,35 @@
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.connection.StorableObject;
public class WorldIdentifiers implements StorableObject {
public static final String OVERWORLD_DEFAULT = "minecraft:overworld";
public static final String NETHER_DEFAULT = "minecraft:the_nether";
public static final String END_DEFAULT = "minecraft:the_end";
private final String overworld;
private final String nether;
private final String end;
public WorldIdentifiers(String overworld) {
this(overworld, NETHER_DEFAULT, END_DEFAULT);
}
public WorldIdentifiers(String overworld, String nether, String end) {
this.overworld = overworld;
this.nether = nether;
this.end = end;
}
public String overworld() {
return this.overworld;
}
public String nether() {
return this.nether;
}
public String end() {
return this.end;
}
}
@@ -0,0 +1,45 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.blockentity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface BlockEntity {
default byte sectionX() {
return (byte) ((packedXZ() >> 4) & 15);
}
default byte sectionZ() {
return (byte) (packedXZ() & 15);
}
byte packedXZ();
short y();
int typeId();
@Nullable CompoundTag tag();
}
@@ -0,0 +1,59 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.blockentity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
public final class BlockEntityImpl implements BlockEntity {
private final byte packedXZ;
private final short y;
private final int typeId;
private final CompoundTag tag;
public BlockEntityImpl(final byte packedXZ, final short y, final int typeId, final CompoundTag tag) {
this.packedXZ = packedXZ;
this.y = y;
this.typeId = typeId;
this.tag = tag;
}
@Override
public byte packedXZ() {
return packedXZ;
}
@Override
public short y() {
return y;
}
@Override
public int typeId() {
return typeId;
}
@Override
public CompoundTag tag() {
return tag;
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft.chunks;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.BitSet;
@@ -147,4 +148,9 @@ public class BaseChunk implements Chunk {
public List<CompoundTag> getBlockEntities() {
return blockEntities;
}
@Override
public List<BlockEntity> blockEntities() {
throw new UnsupportedOperationException();
}
}
@@ -23,11 +23,13 @@
package com.viaversion.viaversion.api.minecraft.chunks;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.BitSet;
import java.util.List;
// TODO specialized sub interfaces
public interface Chunk {
/**
@@ -115,4 +117,11 @@ public interface Chunk {
* @return list of block entities
*/
List<CompoundTag> getBlockEntities();
/**
* Returns a list of block entities.
*
* @return list of block entities
*/
List<BlockEntity> blockEntities();
}
@@ -0,0 +1,136 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.BitSet;
import java.util.List;
public class Chunk1_18 implements Chunk {
protected final int x;
protected final int z;
protected ChunkSection[] sections;
protected CompoundTag heightMap;
protected final List<BlockEntity> blockEntities;
public Chunk1_18(int x, int z, ChunkSection[] sections, CompoundTag heightMap, List<BlockEntity> blockEntities) {
this.x = x;
this.z = z;
this.sections = sections;
this.heightMap = heightMap;
this.blockEntities = blockEntities;
}
@Override
public boolean isBiomeData() {
return false;
}
@Override
public int getX() {
return x;
}
@Override
public int getZ() {
return z;
}
@Override
public boolean isFullChunk() {
return true;
}
@Override
public boolean isIgnoreOldLightData() {
return false;
}
@Override
public void setIgnoreOldLightData(boolean ignoreOldLightData) {
throw new UnsupportedOperationException();
}
@Override
public int getBitmask() {
return -1;
}
@Override
public void setBitmask(int bitmask) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable BitSet getChunkMask() {
return null;
}
@Override
public void setChunkMask(BitSet chunkSectionMask) {
throw new UnsupportedOperationException();
}
@Override
public ChunkSection[] getSections() {
return sections;
}
@Override
public void setSections(ChunkSection[] sections) {
this.sections = sections;
}
@Override
public int @Nullable [] getBiomeData() {
return null;
}
@Override
public void setBiomeData(int @Nullable [] biomeData) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable CompoundTag getHeightMap() {
return heightMap;
}
@Override
public void setHeightMap(final CompoundTag heightMap) {
this.heightMap = heightMap;
}
@Override
public List<CompoundTag> getBlockEntities() {
throw new UnsupportedOperationException();
}
@Override
public List<BlockEntity> blockEntities() {
return blockEntities;
}
}
@@ -32,143 +32,93 @@ public interface ChunkSection {
int SIZE = 16 * 16 * 16; // width * depth * height
/**
* Returns the block index of the given coordinates within a section.
*
* @param x section x
* @param y section y
* @param z section z
* @return section block index
* Size (dimensions) of biomes in a chunks section.
*/
int BIOME_SIZE = 4 * 4 * 4;
static int index(int x, int y, int z) {
return y << 8 | z << 4 | x;
}
/**
* Returns the block state of the given index.
*
* @param idx block index within the section
* @return block state of the given index
*/
int getFlatBlock(int idx);
@Deprecated/*(forRemoval = true)*/
default int getFlatBlock(int idx) {
return palette(PaletteType.BLOCKS).idAt(idx);
}
/**
* Returns the block state of the section coordinate.
*
* @param x section x
* @param y section y
* @param z section z
* @return block state of the given section coordinate
*/
@Deprecated/*(forRemoval = true)*/
default int getFlatBlock(int x, int y, int z) {
return getFlatBlock(index(x, y, z));
}
/**
* Set a block state in the chunk section.
* This method will not update non-air blocks count.
*
* @param idx block index within the section
* @param id raw or flat id of the block state
*/
void setFlatBlock(int idx, int id);
@Deprecated/*(forRemoval = true)*/
default void setFlatBlock(int idx, int id) {
palette(PaletteType.BLOCKS).setIdAt(idx, id);
}
/**
* Set a block state in the chunk section.
* This method will not update non-air blocks count.
*
* @param x section x
* @param y section y
* @param z section z
* @param id raw or flat id of the block state
*/
@Deprecated/*(forRemoval = true)*/
default void setFlatBlock(int x, int y, int z, int id) {
setFlatBlock(index(x, y, z), id);
}
@Deprecated/*(forRemoval = true)*/
default int getBlockWithoutData(int x, int y, int z) {
return getFlatBlock(x, y, z) >> 4;
}
@Deprecated/*(forRemoval = true)*/
default int getBlockData(int x, int y, int z) {
return getFlatBlock(x, y, z) & 0xF;
}
/**
* Set a block in the chunks.
* This method will not update non-air blocks count.
*
* @param x Block X
* @param y Block Y
* @param z Block Z
* @param type The type of the block
* @param data The data value of the block
*/
@Deprecated/*(forRemoval = true)*/
default void setBlockWithData(int x, int y, int z, int type, int data) {
setFlatBlock(index(x, y, z), type << 4 | (data & 0xF));
}
@Deprecated/*(forRemoval = true)*/
default void setBlockWithData(int idx, int type, int data) {
setFlatBlock(idx, type << 4 | (data & 0xF));
}
/**
* Sets a block to the given palette index.
*
* @param idx block index
* @param index palette index
*/
void setPaletteIndex(int idx, int index);
@Deprecated/*(forRemoval = true)*/
default void setPaletteIndex(int idx, int index) {
palette(PaletteType.BLOCKS).setPaletteIndexAt(idx, index);
}
/**
* Returns the palette index of the given block index.
*
* @param idx block index
* @return palette index of the given block index
*/
int getPaletteIndex(int idx);
@Deprecated/*(forRemoval = true)*/
default int getPaletteIndex(int idx) {
return palette(PaletteType.BLOCKS).paletteIndexAt(idx);
}
/**
* Returns the size of the palette.
*
* @return palette size
*/
int getPaletteSize();
@Deprecated/*(forRemoval = true)*/
default int getPaletteSize() {
return palette(PaletteType.BLOCKS).size();
}
/**
* Returns the block state assigned to the given palette index.
*
* @param index palette index
* @return block state assigned to the given palette index
*/
int getPaletteEntry(int index);
@Deprecated/*(forRemoval = true)*/
default int getPaletteEntry(int index) {
return palette(PaletteType.BLOCKS).idByIndex(index);
}
/**
* Assigns a block state assigned to the given palette index.
*
* @param index palette index
* @param id block state
*/
void setPaletteEntry(int index, int id);
@Deprecated/*(forRemoval = true)*/
default void setPaletteEntry(int index, int id) {
palette(PaletteType.BLOCKS).setIdByIndex(index, id);
}
/**
* Replaces a block state in the palette.
*
* @param oldId old block state
* @param newId new block state
*/
void replacePaletteEntry(int oldId, int newId);
@Deprecated/*(forRemoval = true)*/
default void replacePaletteEntry(int oldId, int newId) {
palette(PaletteType.BLOCKS).replaceId(oldId, newId);
}
/**
* Adds a new block state to the palette.
*
* @param id block state
*/
void addPaletteEntry(int id);
@Deprecated/*(forRemoval = true)*/
default void addPaletteEntry(int id) {
palette(PaletteType.BLOCKS).addId(id);
}
/**
* Clears the palette.
*/
void clearPalette();
@Deprecated/*(forRemoval = true)*/
default void clearPalette() {
palette(PaletteType.BLOCKS).clear();
}
/**
* Returns the number of non-air blocks in this section.
@@ -198,4 +148,16 @@ public interface ChunkSection {
@Nullable ChunkSectionLight getLight();
void setLight(@Nullable ChunkSectionLight light);
/**
* Returns the palette of the given type if present.
*
* @param type type of the palette
* @return palette
*/
@Nullable DataPalette palette(PaletteType type);
void addPalette(PaletteType type, DataPalette blockPalette);
void removePalette(PaletteType type);
}
@@ -22,120 +22,31 @@
*/
package com.viaversion.viaversion.api.minecraft.chunks;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.EnumMap;
public class ChunkSectionImpl implements ChunkSection {
private final IntList palette;
private final Int2IntMap inversePalette;
private final int[] blocks;
private final EnumMap<PaletteType, DataPalette> palettes = new EnumMap<>(PaletteType.class);
private ChunkSectionLight light;
private int nonAirBlocksCount;
public ChunkSectionImpl(boolean holdsLight) {
this.blocks = new int[SIZE];
palette = new IntArrayList();
inversePalette = new Int2IntOpenHashMap();
inversePalette.defaultReturnValue(-1);
public ChunkSectionImpl() {
}
public ChunkSectionImpl(final boolean holdsLight) {
addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE));
if (holdsLight) {
this.light = new ChunkSectionLightImpl();
}
}
public ChunkSectionImpl(boolean holdsLight, int expectedPaletteLength) {
this.blocks = new int[SIZE];
public ChunkSectionImpl(final boolean holdsLight, final int expectedPaletteLength) {
addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE, expectedPaletteLength));
if (holdsLight) {
this.light = new ChunkSectionLightImpl();
}
// Pre-size the palette array/map
palette = new IntArrayList(expectedPaletteLength);
inversePalette = new Int2IntOpenHashMap(expectedPaletteLength);
inversePalette.defaultReturnValue(-1);
}
@Override
public int getFlatBlock(int idx) {
int index = blocks[idx];
return palette.getInt(index);
}
@Override
public void setFlatBlock(int idx, int id) {
int index = inversePalette.get(id);
if (index == -1) {
index = palette.size();
palette.add(id);
inversePalette.put(id, index);
}
blocks[idx] = index;
}
@Override
public int getPaletteIndex(int idx) {
return blocks[idx];
}
@Override
public void setPaletteIndex(int idx, int index) {
blocks[idx] = index;
}
@Override
public int getPaletteSize() {
return palette.size();
}
@Override
public int getPaletteEntry(int index) {
return palette.getInt(index);
}
@Override
public void setPaletteEntry(int index, int id) {
int oldId = palette.set(index, id);
if (oldId == id) return;
inversePalette.put(id, index);
if (inversePalette.get(oldId) == index) {
inversePalette.remove(oldId);
for (int i = 0; i < palette.size(); i++) {
if (palette.getInt(i) == oldId) {
inversePalette.put(oldId, i);
break;
}
}
}
}
@Override
public void replacePaletteEntry(int oldId, int newId) {
int index = inversePalette.remove(oldId);
if (index == -1) return;
inversePalette.put(newId, index);
for (int i = 0; i < palette.size(); i++) {
if (palette.getInt(i) == oldId) {
palette.set(i, newId);
}
}
}
@Override
public void addPaletteEntry(int id) {
inversePalette.put(id, palette.size());
palette.add(id);
}
@Override
public void clearPalette() {
palette.clear();
inversePalette.clear();
}
@Override
@@ -144,7 +55,7 @@ public class ChunkSectionImpl implements ChunkSection {
}
@Override
public void setNonAirBlocksCount(int nonAirBlocksCount) {
public void setNonAirBlocksCount(final int nonAirBlocksCount) {
this.nonAirBlocksCount = nonAirBlocksCount;
}
@@ -154,7 +65,22 @@ public class ChunkSectionImpl implements ChunkSection {
}
@Override
public void setLight(@Nullable ChunkSectionLight light) {
public void setLight(@Nullable final ChunkSectionLight light) {
this.light = light;
}
@Override
public DataPalette palette(final PaletteType type) {
return palettes.get(type);
}
@Override
public void addPalette(final PaletteType type, final DataPalette palette) {
palettes.put(type, palette);
}
@Override
public void removePalette(final PaletteType type) {
palettes.remove(type);
}
}
@@ -0,0 +1,137 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
public interface DataPalette {
/**
* Returns the packet section index of the given coordinates.
*
* @param x x
* @param y y
* @param z z
* @return packed section index of the given coordinates
*/
int index(final int x, final int y, final int z);
/**
* Returns the value of the given chunk coordinate.
*
* @param sectionCoordinate section index within the section
* @return section state of the given index
*/
int idAt(int sectionCoordinate);
/**
* Returns the value of the section coordinate.
*
* @param sectionX section x
* @param sectionY section y
* @param sectionZ section z
* @return id of the given section coordinate
*/
default int idAt(final int sectionX, final int sectionY, final int sectionZ) {
return idAt(index(sectionX, sectionY, sectionZ));
}
/**
* Set a value in the chunk section.
* This method does not update non-air blocks count.
*
* @param sectionCoordinate section index within the section
* @param id id value
*/
void setIdAt(int sectionCoordinate, int id);
/**
* Set a value in the chunk section.
* This method does not update non-air blocks count.
*
* @param sectionX section x
* @param sectionY section y
* @param sectionZ section z
* @param id id value
*/
default void setIdAt(final int sectionX, final int sectionY, final int sectionZ, final int id) {
setIdAt(index(sectionX, sectionY, sectionZ), id);
}
/**
* Returns the id assigned to the given palette index.
*
* @param index palette index
* @return id assigned to the given palette index
*/
int idByIndex(int index);
/**
* Assigns an id assigned to the given palette index.
*
* @param index palette index
* @param id id value
*/
void setIdByIndex(int index, int id);
/**
* Returns the palette index of the given section index.
*
* @param packedCoordinate section index
* @return palette index of the given section index
*/
int paletteIndexAt(int packedCoordinate);
/**
* Sets the index of the given section coordinate.
*
* @param sectionCoordinate section index
* @param index palette index
*/
void setPaletteIndexAt(int sectionCoordinate, int index);
/**
* Adds a new id to the palette.
*
* @param id id value
*/
void addId(int id);
/**
* Replaces an id in the palette.
*
* @param oldId old id
* @param newId new id
*/
void replaceId(int oldId, int newId);
/**
* Returns the size of the palette.
*
* @return palette size
*/
int size();
/**
* Clears the palette.
*/
void clear();
}
@@ -0,0 +1,134 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
public final class DataPaletteImpl implements DataPalette {
private final IntList palette;
private final Int2IntMap inversePalette;
private final int[] values;
private final int sizeBits;
public DataPaletteImpl(final int valuesLength) {
this(valuesLength, 8);
}
public DataPaletteImpl(final int valuesLength, final int expectedPaletteLength) {
this.values = new int[valuesLength];
sizeBits = Integer.numberOfTrailingZeros(valuesLength) / 3;
// Pre-size the palette array/map
palette = new IntArrayList(expectedPaletteLength);
inversePalette = new Int2IntOpenHashMap(expectedPaletteLength);
inversePalette.defaultReturnValue(-1);
}
@Override
public int index(final int x, final int y, final int z) {
return (y << this.sizeBits | z) << this.sizeBits | x;
}
@Override
public int idAt(final int sectionCoordinate) {
final int index = values[sectionCoordinate];
return palette.getInt(index);
}
@Override
public void setIdAt(final int sectionCoordinate, final int id) {
int index = inversePalette.get(id);
if (index == -1) {
index = palette.size();
palette.add(id);
inversePalette.put(id, index);
}
values[sectionCoordinate] = index;
}
@Override
public int paletteIndexAt(final int packedCoordinate) {
return values[packedCoordinate];
}
@Override
public void setPaletteIndexAt(final int sectionCoordinate, final int index) {
values[sectionCoordinate] = index;
}
@Override
public int size() {
return palette.size();
}
@Override
public int idByIndex(final int index) {
return palette.getInt(index);
}
@Override
public void setIdByIndex(final int index, final int id) {
final int oldId = palette.set(index, id);
if (oldId == id) return;
inversePalette.put(id, index);
if (inversePalette.get(oldId) == index) {
inversePalette.remove(oldId);
for (int i = 0; i < palette.size(); i++) {
if (palette.getInt(i) == oldId) {
inversePalette.put(oldId, i);
break;
}
}
}
}
@Override
public void replaceId(final int oldId, final int newId) {
final int index = inversePalette.remove(oldId);
if (index == -1) return;
inversePalette.put(newId, index);
for (int i = 0; i < palette.size(); i++) {
if (palette.getInt(i) == oldId) {
palette.set(i, newId);
}
}
}
@Override
public void addId(final int id) {
inversePalette.put(id, palette.size());
palette.add(id);
}
@Override
public void clear() {
palette.clear();
inversePalette.clear();
}
}
@@ -0,0 +1,44 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
public enum PaletteType {
BLOCKS(ChunkSection.SIZE, 8),
BIOMES(ChunkSection.BIOME_SIZE, 3);
private final int size;
private final int highestBitsPerValue;
PaletteType(final int size, final int highestBitsPerValue) {
this.size = size;
this.highestBitsPerValue = highestBitsPerValue;
}
public int size() {
return size;
}
public int highestBitsPerValue() {
return highestBitsPerValue;
}
}
@@ -28,7 +28,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
// 1.11 Entity / Object ids TODO maybe in the future instead of copying it, some api.
// 1.11 Entity / Object ids
public class Entity1_11Types {
public static EntityType getTypeFromId(int typeID, boolean isObject) {
@@ -39,4 +39,44 @@ public interface MetaType {
* @return Type id as an integer
*/
int typeId();
static MetaType create(final int typeId, final Type<?> type) {
return new MetaTypeImpl(typeId, type);
}
final class MetaTypeImpl implements MetaType {
private final int typeId;
private final Type<?> type;
MetaTypeImpl(final int typeId, final Type<?> type) {
this.typeId = typeId;
this.type = type;
}
@Override
public int typeId() {
return typeId;
}
@Override
public Type<?> type() {
return type;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final MetaTypeImpl metaType = (MetaTypeImpl) o;
if (typeId != metaType.typeId) return false;
return type.equals(metaType.type);
}
@Override
public int hashCode() {
int result = typeId;
result = 31 * result + type.hashCode();
return result;
}
}
}
@@ -105,7 +105,7 @@ public final class Metadata {
Preconditions.checkNotNull(metaType);
if (value != null && !metaType.type().getOutputClass().isAssignableFrom(value.getClass())) {
throw new IllegalArgumentException("Metadata value and metaType are incompatible. Type=" + metaType
+ ", value=" + (value != null ? value + " (" + value.getClass().getSimpleName() + ")" : "null"));
+ ", value=" + value + " (" + value.getClass().getSimpleName() + ")");
}
return value;
}
@@ -121,7 +121,7 @@ public final class Metadata {
if (o == null || getClass() != o.getClass()) return false;
Metadata metadata = (Metadata) o;
if (id != metadata.id) return false;
if (metaType != metaType) return false;
if (metaType != metadata.metaType) return false;
return Objects.equals(value, metadata.value);
}
@@ -20,21 +20,32 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.AbstractMetaListType;
import io.netty.buffer.ByteBuf;
public class MetadataList1_8Type extends AbstractMetaListType {
@Override
protected Type<Metadata> getType() {
return Types1_8.METADATA;
public abstract class AbstractMetaTypes implements MetaTypes {
private final MetaType[] values;
protected AbstractMetaTypes(final int values) {
this.values = new MetaType[values];
}
@Override
protected void writeEnd(final Type<Metadata> type, final ByteBuf buffer) throws Exception {
buffer.writeByte(0x7f);
public MetaType byId(final int id) {
return values[id];
}
@Override
public MetaType[] values() {
return values;
}
protected MetaType add(final int typeId, final Type<?> type) {
final MetaType metaType = MetaType.create(typeId, type);
values[typeId] = metaType;
return metaType;
}
}
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
@Deprecated/*(forRemoval = true)*/
public enum MetaType1_13 implements MetaType {
Byte(0, Type.BYTE),
VarInt(1, Type.VAR_INT),
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_13_2;
@Deprecated/*(forRemoval = true)*/
public enum MetaType1_13_2 implements MetaType {
Byte(0, Type.BYTE),
VarInt(1, Type.VAR_INT),
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_14;
@Deprecated/*(forRemoval = true)*/
public enum MetaType1_14 implements MetaType {
Byte(0, Type.BYTE),
VarInt(1, Type.VAR_INT),
@@ -0,0 +1,73 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_16;
@Deprecated/*(forRemoval = true)*/
public enum MetaType1_16 implements MetaType {
BYTE(0, Type.BYTE),
VAR_INT(1, Type.VAR_INT),
FLOAT(2, Type.FLOAT),
STRING(3, Type.STRING),
COMPONENT(4, Type.COMPONENT),
OPT_COMPONENT(5, Type.OPTIONAL_COMPONENT),
ITEM(6, Type.FLAT_VAR_INT_ITEM),
BOOLEAN(7, Type.BOOLEAN),
ROTATION(8, Type.ROTATION),
POSITION(9, Type.POSITION1_14),
OPT_POSITION(10, Type.OPTIONAL_POSITION_1_14),
DIRECTION(11, Type.VAR_INT),
OPT_UUID(12, Type.OPTIONAL_UUID),
BLOCK_STATE(13, Type.VAR_INT),
NBT(14, Type.NBT),
PARTICLE(15, Types1_16.PARTICLE),
VILLAGER_DATA(16, Type.VILLAGER_DATA),
OPT_VAR_INT(17, Type.OPTIONAL_VAR_INT),
POSE(18, Type.VAR_INT);
private static final MetaType1_16[] VALUES = values();
private final int typeId;
private final Type type;
MetaType1_16(int typeId, Type type) {
this.typeId = typeId;
this.type = type;
}
public static MetaType1_16 byId(int id) {
return VALUES[id];
}
@Override
public int typeId() {
return typeId;
}
@Override
public Type type() {
return type;
}
}
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_17;
@Deprecated/*(forRemoval = true)*/
public enum MetaType1_17 implements MetaType {
BYTE(0, Type.BYTE),
VAR_INT(1, Type.VAR_INT),
@@ -0,0 +1,73 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.Types1_18;
@Deprecated/*(forRemoval = true)*/
public enum MetaType1_18 implements MetaType {
BYTE(0, Type.BYTE),
VAR_INT(1, Type.VAR_INT),
FLOAT(2, Type.FLOAT),
STRING(3, Type.STRING),
COMPONENT(4, Type.COMPONENT),
OPT_COMPONENT(5, Type.OPTIONAL_COMPONENT),
ITEM(6, Type.FLAT_VAR_INT_ITEM),
BOOLEAN(7, Type.BOOLEAN),
ROTATION(8, Type.ROTATION),
POSITION(9, Type.POSITION1_14),
OPT_POSITION(10, Type.OPTIONAL_POSITION_1_14),
DIRECTION(11, Type.VAR_INT),
OPT_UUID(12, Type.OPTIONAL_UUID),
BLOCK_STATE(13, Type.VAR_INT),
NBT(14, Type.NBT),
PARTICLE(15, Types1_18.PARTICLE),
VILLAGER_DATA(16, Type.VILLAGER_DATA),
OPT_VAR_INT(17, Type.OPTIONAL_VAR_INT),
POSE(18, Type.VAR_INT);
private static final MetaType1_18[] VALUES = values();
private final int typeId;
private final Type type;
MetaType1_18(int typeId, Type type) {
this.typeId = typeId;
this.type = type;
}
public static MetaType1_18 byId(int id) {
return VALUES[id];
}
@Override
public int typeId() {
return typeId;
}
@Override
public Type type() {
return type;
}
}
@@ -0,0 +1,44 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
public interface MetaTypes {
/**
* Returns the meta type by the given id.
*
* @param id type id
* @return meta type by id
* @throws IndexOutOfBoundsException if id is out of bounds
*/
MetaType byId(int id);
/**
* Returns an array of meta types.
*
* @return array of meta types
*/
MetaType[] values();
}
@@ -0,0 +1,52 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.ParticleType;
public final class MetaTypes1_13 extends AbstractMetaTypes {
public final MetaType byteType = add(0, Type.BYTE);
public final MetaType varIntType = add(1, Type.VAR_INT);
public final MetaType floatType = add(2, Type.FLOAT);
public final MetaType stringType = add(3, Type.STRING);
public final MetaType componentType = add(4, Type.COMPONENT);
public final MetaType optionalComponentType = add(5, Type.OPTIONAL_COMPONENT);
public final MetaType itemType = add(6, Type.FLAT_ITEM);
public final MetaType booleanType = add(7, Type.BOOLEAN);
public final MetaType rotationType = add(8, Type.ROTATION);
public final MetaType positionType = add(9, Type.POSITION);
public final MetaType optionalPositionType = add(10, Type.OPTIONAL_POSITION);
public final MetaType directionType = add(11, Type.VAR_INT);
public final MetaType optionalUUIDType = add(12, Type.OPTIONAL_UUID);
public final MetaType blockStateType = add(13, Type.VAR_INT);
public final MetaType nbtType = add(14, Type.NBT);
public final MetaType particleType;
public MetaTypes1_13(final ParticleType particleType) {
super(16);
this.particleType = add(15, particleType);
}
}
@@ -0,0 +1,52 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.ParticleType;
public final class MetaTypes1_13_2 extends AbstractMetaTypes {
public final MetaType byteType = add(0, Type.BYTE);
public final MetaType varIntType = add(1, Type.VAR_INT);
public final MetaType floatType = add(2, Type.FLOAT);
public final MetaType stringType = add(3, Type.STRING);
public final MetaType componentType = add(4, Type.COMPONENT);
public final MetaType optionalComponentType = add(5, Type.OPTIONAL_COMPONENT);
public final MetaType itemType = add(6, Type.FLAT_VAR_INT_ITEM);
public final MetaType booleanType = add(7, Type.BOOLEAN);
public final MetaType rotationType = add(8, Type.ROTATION);
public final MetaType positionType = add(9, Type.POSITION);
public final MetaType optionalPositionType = add(10, Type.OPTIONAL_POSITION);
public final MetaType directionType = add(11, Type.VAR_INT);
public final MetaType optionalUUIDType = add(12, Type.OPTIONAL_UUID);
public final MetaType blockStateType = add(13, Type.VAR_INT);
public final MetaType nbtType = add(14, Type.NBT);
public final MetaType particleType;
public MetaTypes1_13_2(final ParticleType particleType) {
super(16);
this.particleType = add(15, particleType);
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.metadata.types;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.ParticleType;
public final class MetaTypes1_14 extends AbstractMetaTypes {
public final MetaType byteType = add(0, Type.BYTE);
public final MetaType varIntType = add(1, Type.VAR_INT);
public final MetaType floatType = add(2, Type.FLOAT);
public final MetaType stringType = add(3, Type.STRING);
public final MetaType componentType = add(4, Type.COMPONENT);
public final MetaType optionalComponentType = add(5, Type.OPTIONAL_COMPONENT);
public final MetaType itemType = add(6, Type.FLAT_VAR_INT_ITEM);
public final MetaType booleanType = add(7, Type.BOOLEAN);
public final MetaType rotationType = add(8, Type.ROTATION);
public final MetaType positionType = add(9, Type.POSITION1_14);
public final MetaType optionalPositionType = add(10, Type.OPTIONAL_POSITION_1_14);
public final MetaType directionType = add(11, Type.VAR_INT);
public final MetaType optionalUUIDType = add(12, Type.OPTIONAL_UUID);
public final MetaType blockStateType = add(13, Type.VAR_INT);
public final MetaType nbtType = add(14, Type.NBT);
public final MetaType particleType;
public final MetaType villagerDatatType = add(16, Type.VILLAGER_DATA);
public final MetaType optionalVarIntType = add(17, Type.OPTIONAL_VAR_INT);
public final MetaType poseType = add(18, Type.VAR_INT);
public MetaTypes1_14(final ParticleType particleType) {
super(19);
this.particleType = add(15, particleType);
}
}
@@ -39,8 +39,12 @@ import java.nio.file.Path;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
// Specific Via changes:
// - Use OpenNBT tags
// - Added readString/writeString methods from TagStringIO
// - Has not been updated for the sake of keeping the class simple
/**
* See https://github.com/KyoriPowered/adventure.
* Serialization operations for binary tags.
*/
public final class BinaryTagIO {
private BinaryTagIO() {
@@ -1,7 +1,7 @@
/*
* This file is part of adventure, licensed under the MIT License.
*
* Copyright (c) 2017-2020 KyoriPowered
* Copyright (c) 2017-2021 KyoriPowered
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,10 @@
*/
package com.viaversion.viaversion.api.minecraft.nbt;
/* package */ final class CharBuffer {
/**
* A character buffer designed to be inspected by a parser.
*/
final class CharBuffer {
private final CharSequence sequence;
private int index;
@@ -32,7 +35,7 @@ package com.viaversion.viaversion.api.minecraft.nbt;
}
/**
* Get the character at the current position
* Get the character at the current position.
*
* @return The current character
*/
@@ -45,7 +48,7 @@ package com.viaversion.viaversion.api.minecraft.nbt;
}
/**
* Get the current character and advance
* Get the current character and advance.
*
* @return current character
*/
@@ -62,6 +65,10 @@ package com.viaversion.viaversion.api.minecraft.nbt;
return this.index < this.sequence.length();
}
public boolean hasMore(final int offset) {
return this.index + offset < this.sequence.length();
}
/**
* Search for the provided token, and advance the reader index past the {@code until} character.
*
@@ -109,6 +116,23 @@ package com.viaversion.viaversion.api.minecraft.nbt;
return this;
}
/**
* If the next non-whitespace character is {@code token}, advance past it.
*
* <p>This method always consumes whitespace.</p>
*
* @param token next non-whitespace character to query
* @return if the next non-whitespace character is {@code token}
*/
public boolean takeIf(final char token) {
this.skipWhitespace();
if (this.hasMore() && this.peek() == token) {
this.advance();
return true;
}
return false;
}
public CharBuffer skipWhitespace() {
while (this.hasMore() && Character.isWhitespace(this.peek())) this.advance();
return this;
@@ -26,9 +26,9 @@ package com.viaversion.viaversion.api.minecraft.nbt;
import java.io.IOException;
/**
* An exception thrown when parsing a string tag
* An exception thrown when parsing a string tag.
*/
/* package */ class StringTagParseException extends IOException {
class StringTagParseException extends IOException {
private static final long serialVersionUID = -3001637554903912905L;
private final CharSequence buffer;
private final int position;
@@ -39,8 +39,6 @@ import java.io.IOException;
this.position = position;
}
// TODO: Provide more specific position information
@Override
public String getMessage() {
return super.getMessage() + "(at position " + this.position + ")";
@@ -1,7 +1,7 @@
/*
* This file is part of adventure, licensed under the MIT License.
*
* Copyright (c) 2017-2020 KyoriPowered
* Copyright (c) 2017-2021 KyoriPowered
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -37,33 +37,39 @@ import com.github.steveice10.opennbt.tag.builtin.NumberTag;
import com.github.steveice10.opennbt.tag.builtin.ShortTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
// Specific Via changes:
// - Use OpenNBT tags
// - Small byteArray() optimization
// - acceptLegacy = true by default
final class TagStringReader {
private static final int MAX_DEPTH = 512;
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final int[] EMPTY_INT_ARRAY = new int[0];
private static final long[] EMPTY_LONG_ARRAY = new long[0];
/**
* See https://github.com/KyoriPowered/adventure.
*/
/* package */ final class TagStringReader {
private final CharBuffer buffer;
private boolean acceptLegacy = true; // Via - always true
private int depth;
public TagStringReader(final CharBuffer buffer) {
TagStringReader(final CharBuffer buffer) {
this.buffer = buffer;
}
public CompoundTag compound() throws StringTagParseException {
this.buffer.expect(Tokens.COMPOUND_BEGIN);
final CompoundTag compoundTag = new CompoundTag();
if (this.buffer.peek() == Tokens.COMPOUND_END) {
this.buffer.take();
if (this.buffer.takeIf(Tokens.COMPOUND_END)) {
return compoundTag;
}
while (this.buffer.hasMore()) {
final String key = this.key();
final Tag tag = this.tag();
compoundTag.put(key, tag);
compoundTag.put(this.key(), this.tag());
if (this.separatorOrCompleteWith(Tokens.COMPOUND_END)) {
return compoundTag;
}
@@ -74,19 +80,16 @@ import java.util.stream.IntStream;
public ListTag list() throws StringTagParseException {
final ListTag listTag = new ListTag();
this.buffer.expect(Tokens.ARRAY_BEGIN);
final boolean prefixedIndex = this.buffer.peek() == '0' && this.buffer.peek(1) == ':';
final boolean prefixedIndex = this.acceptLegacy && this.buffer.peek() == '0' && this.buffer.peek(1) == ':';
if (!prefixedIndex && this.buffer.takeIf(Tokens.ARRAY_END)) {
return listTag;
}
while (this.buffer.hasMore()) {
if (this.buffer.peek() == Tokens.ARRAY_END) {
this.buffer.advance();
return listTag;
}
if (prefixedIndex) {
this.buffer.takeUntil(':');
}
final Tag next = this.tag();
// TODO: validate type
listTag.add(next);
if (this.separatorOrCompleteWith(Tokens.ARRAY_END)) {
return listTag;
@@ -100,11 +103,12 @@ import java.util.stream.IntStream;
*
* @return array-typed tag
*/
public Tag array(final char elementType) throws StringTagParseException {
public Tag array(char elementType) throws StringTagParseException {
this.buffer.expect(Tokens.ARRAY_BEGIN)
.expect(elementType)
.expect(Tokens.ARRAY_SIGNATURE_SEPARATOR);
elementType = Character.toLowerCase(elementType);
if (elementType == Tokens.TYPE_BYTE) {
return new ByteArrayTag(this.byteArray());
} else if (elementType == Tokens.TYPE_INT) {
@@ -117,19 +121,23 @@ import java.util.stream.IntStream;
}
private byte[] byteArray() throws StringTagParseException {
final List<Byte> bytes = new ArrayList<>();
if (this.buffer.takeIf(Tokens.ARRAY_END)) {
return EMPTY_BYTE_ARRAY;
}
final IntList bytes = new IntArrayList(); // Via - no boxing
while (this.buffer.hasMore()) {
final CharSequence value = this.buffer.skipWhitespace().takeUntil(Tokens.TYPE_BYTE);
try {
bytes.add(Byte.valueOf(value.toString()));
bytes.add(Byte.parseByte(value.toString())); // Via
} catch (final NumberFormatException ex) {
throw this.buffer.makeError("All elements of a byte array must be bytes!");
}
if (this.separatorOrCompleteWith(Tokens.ARRAY_END)) {
final byte[] result = new byte[bytes.size()];
for (int i = 0; i < bytes.size(); ++i) { // todo yikes, let's do less boxing
result[i] = bytes.get(i);
for (int i = 0; i < bytes.size(); ++i) {
result[i] = (byte) bytes.getInt(i); // Via
}
return result;
}
@@ -138,6 +146,10 @@ import java.util.stream.IntStream;
}
private int[] intArray() throws StringTagParseException {
if (this.buffer.takeIf(Tokens.ARRAY_END)) {
return EMPTY_INT_ARRAY;
}
final IntStream.Builder builder = IntStream.builder();
while (this.buffer.hasMore()) {
final Tag value = this.tag();
@@ -153,21 +165,21 @@ import java.util.stream.IntStream;
}
private long[] longArray() throws StringTagParseException {
final List<Long> longs = new ArrayList<>();
if (this.buffer.takeIf(Tokens.ARRAY_END)) {
return EMPTY_LONG_ARRAY;
}
final LongStream.Builder longs = LongStream.builder();
while (this.buffer.hasMore()) {
final CharSequence value = this.buffer.skipWhitespace().takeUntil(Tokens.TYPE_LONG);
try {
longs.add(Long.valueOf(value.toString()));
longs.add(Long.parseLong(value.toString()));
} catch (final NumberFormatException ex) {
throw this.buffer.makeError("All elements of a long array must be longs!");
}
if (this.separatorOrCompleteWith(Tokens.ARRAY_END)) {
final long[] result = new long[longs.size()];
for (int i = 0; i < longs.size(); ++i) { // todo yikes
result[i] = longs.get(i);
}
return result;
return longs.build().toArray();
}
}
throw this.buffer.makeError("Reached end of document without array close");
@@ -182,7 +194,21 @@ import java.util.stream.IntStream;
}
final StringBuilder builder = new StringBuilder();
while (this.buffer.peek() != ':') { // DO NOT CHECK FOR CHARACTER VALIDITY; LEGACY NBT ALLOWS ANY CHARACTER, EVEN WHEN UNQUOTED
while (this.buffer.hasMore()) {
final char peek = this.buffer.peek();
if (!Tokens.id(peek)) {
if (this.acceptLegacy) {
// In legacy format, a key is any non-colon character, with escapes allowed
if (peek == Tokens.ESCAPE_MARKER) {
this.buffer.take(); // skip
continue;
} else if (peek != Tokens.COMPOUND_KEY_TERMINATOR) {
builder.append(this.buffer.take());
continue;
}
}
break;
}
builder.append(this.buffer.take());
}
return builder.toString();
@@ -192,107 +218,122 @@ import java.util.stream.IntStream;
}
public Tag tag() throws StringTagParseException {
final char startToken = this.buffer.skipWhitespace().peek();
switch (startToken) {
case Tokens.COMPOUND_BEGIN:
return this.compound();
case Tokens.ARRAY_BEGIN:
if (this.buffer.peek(2) == ';') { // we know we're an array tag
return this.array(this.buffer.peek(1));
} else {
return this.list();
}
case Tokens.SINGLE_QUOTE:
case Tokens.DOUBLE_QUOTE:
// definitely a string tag
this.buffer.advance();
return new StringTag(unescape(this.buffer.takeUntil(startToken).toString()));
default: // scalar
return this.scalar();
if (this.depth++ > MAX_DEPTH) {
throw this.buffer.makeError("Exceeded maximum allowed depth of " + MAX_DEPTH + " when reading tag");
}
try {
final char startToken = this.buffer.skipWhitespace().peek();
switch (startToken) {
case Tokens.COMPOUND_BEGIN:
return this.compound();
case Tokens.ARRAY_BEGIN:
// Maybe add in a legacy-only mode to read those?
if (this.buffer.hasMore(2) && this.buffer.peek(2) == ';') { // we know we're an array tag
return this.array(this.buffer.peek(1));
} else {
return this.list();
}
case Tokens.SINGLE_QUOTE:
case Tokens.DOUBLE_QUOTE:
// definitely a string tag
this.buffer.advance();
return new StringTag(unescape(this.buffer.takeUntil(startToken).toString()));
default: // scalar
return this.scalar();
}
} finally {
this.depth--;
}
}
/**
* A tag that is definitely some sort of scalar
* A tag that is definitely some sort of scalar.
*
* <p>Does not detect quoted strings, so </p>
* <p>Does not detect quoted strings, so those should have been parsed already.</p>
*
* @return a parsed tag
*/
private Tag scalar() {
final StringBuilder builder = new StringBuilder();
boolean possiblyNumeric = true;
int noLongerNumericAt = -1;
while (this.buffer.hasMore()) {
final char current = this.buffer.peek();
if (possiblyNumeric && !Tokens.numeric(current)) {
if (builder.length() != 0) {
Tag result = null;
try {
switch (Character.toUpperCase(current)) { // try to read and return as a number
// case Tokens.TYPE_INTEGER: // handled below, ints are ~special~
case Tokens.TYPE_BYTE:
result = new ByteTag(Byte.parseByte(builder.toString()));
break;
case Tokens.TYPE_SHORT:
result = new ShortTag(Short.parseShort(builder.toString()));
break;
case Tokens.TYPE_LONG:
result = new LongTag(Long.parseLong(builder.toString()));
break;
case Tokens.TYPE_FLOAT:
result = new FloatTag(Float.parseFloat(builder.toString()));
break;
case Tokens.TYPE_DOUBLE:
result = new DoubleTag(Double.parseDouble(builder.toString()));
break;
}
} catch (final NumberFormatException ex) {
possiblyNumeric = false; // fallback to treating as a String
}
if (result != null) {
this.buffer.take();
return result;
}
}
}
char current = this.buffer.peek();
if (current == '\\') { // escape -- we are significantly more lenient than original format at the moment
this.buffer.advance();
builder.append(this.buffer.take());
current = this.buffer.take();
} else if (Tokens.id(current)) {
builder.append(this.buffer.take());
this.buffer.advance();
} else { // end of value
break;
}
builder.append(current);
if (noLongerNumericAt == -1 && !Tokens.numeric(current)) {
noLongerNumericAt = builder.length();
}
}
// if we run out of content without an explicit value separator, then we're either an integer or string tag -- all others have a character at the end
final int length = builder.length();
final String built = builder.toString();
if (possiblyNumeric) {
if (noLongerNumericAt == length) {
final char last = built.charAt(length - 1);
try {
switch (Character.toLowerCase(last)) { // try to read and return as a number
case Tokens.TYPE_BYTE:
return new ByteTag(Byte.parseByte(built.substring(0, length - 1)));
case Tokens.TYPE_SHORT:
return new ShortTag(Short.parseShort(built.substring(0, length - 1)));
case Tokens.TYPE_INT:
return new IntTag(Integer.parseInt(built.substring(0, length - 1)));
case Tokens.TYPE_LONG:
return new LongTag(Long.parseLong(built.substring(0, length - 1)));
case Tokens.TYPE_FLOAT:
final float floatValue = Float.parseFloat(built.substring(0, length - 1));
if (Float.isFinite(floatValue)) { // don't accept NaN and Infinity
return new FloatTag(floatValue);
}
break;
case Tokens.TYPE_DOUBLE:
final double doubleValue = Double.parseDouble(built.substring(0, length - 1));
if (Double.isFinite(doubleValue)) { // don't accept NaN and Infinity
return new DoubleTag(doubleValue);
}
break;
}
} catch (final NumberFormatException ignored) {
}
} else if (noLongerNumericAt == -1) { // if we run out of content without an explicit value separator, then we're either an integer or string tag -- all others have a character at the end
try {
return new IntTag(Integer.parseInt(built));
} catch (final NumberFormatException ex) {
// ignore
if (built.indexOf('.') != -1) {
try {
return new DoubleTag(Double.parseDouble(built));
} catch (final NumberFormatException ex2) {
// ignore
}
}
}
}
if (built.equalsIgnoreCase(Tokens.LITERAL_TRUE)) {
return new ByteTag((byte) 1);
} else if (built.equalsIgnoreCase(Tokens.LITERAL_FALSE)) {
return new ByteTag((byte) 0);
}
return new StringTag(built);
}
private boolean separatorOrCompleteWith(final char endCharacter) throws StringTagParseException {
if (this.buffer.skipWhitespace().peek() == endCharacter) {
this.buffer.take();
if (this.buffer.takeIf(endCharacter)) {
return true;
}
this.buffer.expect(Tokens.VALUE_SEPARATOR);
if (this.buffer.skipWhitespace().peek() == endCharacter) {
this.buffer.take();
return true;
}
return false;
return this.buffer.takeIf(endCharacter);
}
/**
* Remove simple escape sequences from a string
* Remove simple escape sequences from a string.
*
* @param withEscapes input string with escapes
* @return string with escapes processed
@@ -311,4 +352,8 @@ import java.util.stream.IntStream;
output.append(withEscapes.substring(lastEscape));
return output.toString();
}
public void legacy(final boolean acceptLegacy) {
this.acceptLegacy = acceptLegacy;
}
}
@@ -33,6 +33,7 @@ import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.LongArrayTag;
import com.github.steveice10.opennbt.tag.builtin.LongTag;
import com.github.steveice10.opennbt.tag.builtin.NumberTag;
import com.github.steveice10.opennbt.tag.builtin.ShortTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
@@ -41,12 +42,16 @@ import java.io.IOException;
import java.io.Writer;
import java.util.Map;
// Specific Via changes:
// - Use OpenNBT tags
// - Has not been updated to support pretty printing and legacy writing since that is not needed
/**
* See https://github.com/KyoriPowered/adventure.
* An emitter for the SNBT format.
*
* <p>Details on the format are described in the package documentation.</p>
*/
/* package */ final class TagStringWriter implements AutoCloseable {
final class TagStringWriter implements AutoCloseable {
private final Appendable out;
private final String indent = " "; // TODO: pretty-printing
private int level;
/**
* Whether a {@link Tokens#VALUE_SEPARATOR} needs to be printed before the beginning of the next object.
@@ -73,17 +78,17 @@ import java.util.Map;
} else if (tag instanceof StringTag) {
return this.value(((StringTag) tag).getValue(), Tokens.EOF);
} else if (tag instanceof ByteTag) {
return this.value(Byte.toString(((ByteTag) tag).asByte()), Tokens.TYPE_BYTE);
return this.value(Byte.toString(((NumberTag) tag).asByte()), Tokens.TYPE_BYTE);
} else if (tag instanceof ShortTag) {
return this.value(Short.toString(((ShortTag) tag).asShort()), Tokens.TYPE_SHORT);
return this.value(Short.toString(((NumberTag) tag).asShort()), Tokens.TYPE_SHORT);
} else if (tag instanceof IntTag) {
return this.value(Integer.toString(((IntTag) tag).asInt()), Tokens.TYPE_INT);
return this.value(Integer.toString(((NumberTag) tag).asInt()), Tokens.TYPE_INT);
} else if (tag instanceof LongTag) {
return this.value(Long.toString(((LongTag) tag).asLong()), Tokens.TYPE_LONG);
return this.value(Long.toString(((NumberTag) tag).asLong()), Character.toUpperCase(Tokens.TYPE_LONG)); // special case
} else if (tag instanceof FloatTag) {
return this.value(Float.toString(((FloatTag) tag).asFloat()), Tokens.TYPE_FLOAT);
return this.value(Float.toString(((NumberTag) tag).asFloat()), Tokens.TYPE_FLOAT);
} else if (tag instanceof DoubleTag) {
return this.value(Double.toString(((DoubleTag) tag).asDouble()), Tokens.TYPE_DOUBLE);
return this.value(Double.toString(((NumberTag) tag).asDouble()), Tokens.TYPE_DOUBLE);
} else {
throw new IOException("Unknown tag type: " + tag.getClass().getSimpleName());
// unknown!
@@ -92,7 +97,7 @@ import java.util.Map;
private TagStringWriter writeCompound(final CompoundTag tag) throws IOException {
this.beginCompound();
for (Map.Entry<String, Tag> entry : tag.entrySet()) {
for (final Map.Entry<String, Tag> entry : tag.entrySet()) {
this.key(entry.getKey());
this.writeTag(entry.getValue());
}
@@ -165,7 +170,7 @@ import java.util.Map;
public TagStringWriter key(final String key) throws IOException {
this.printAndResetSeparator();
this.writeMaybeQuoted(key, false);
this.out.append(Tokens.COMPOUND_KEY_TERMINATOR); // TODO: spacing/pretty-printing
this.out.append(Tokens.COMPOUND_KEY_TERMINATOR);
return this;
}
@@ -216,7 +221,7 @@ import java.util.Map;
}
}
}
if (requireQuotes) { // TODO: single quotes
if (requireQuotes) {
this.out.append(Tokens.DOUBLE_QUOTE);
this.out.append(escape(content, Tokens.DOUBLE_QUOTE));
this.out.append(Tokens.DOUBLE_QUOTE);
@@ -244,7 +249,6 @@ import java.util.Map;
}
}
@Override
public void close() throws IOException {
if (this.level != 0) {
@@ -1,7 +1,7 @@
/*
* This file is part of adventure, licensed under the MIT License.
*
* Copyright (c) 2017-2020 KyoriPowered
* Copyright (c) 2017-2021 KyoriPowered
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,10 +23,7 @@
*/
package com.viaversion.viaversion.api.minecraft.nbt;
/**
* See https://github.com/KyoriPowered/adventure.
*/
/* package */ final class Tokens {
final class Tokens {
// Compounds
static final char COMPOUND_BEGIN = '{';
static final char COMPOUND_END = '}';
@@ -43,20 +40,24 @@ package com.viaversion.viaversion.api.minecraft.nbt;
static final char DOUBLE_QUOTE = '"';
static final char ESCAPE_MARKER = '\\';
static final char TYPE_BYTE = 'B';
static final char TYPE_SHORT = 'S';
static final char TYPE_INT = 'I'; // array only
static final char TYPE_LONG = 'L';
static final char TYPE_FLOAT = 'F';
static final char TYPE_DOUBLE = 'D';
static final char TYPE_BYTE = 'b';
static final char TYPE_SHORT = 's';
static final char TYPE_INT = 'i'; // array only
static final char TYPE_LONG = 'l';
static final char TYPE_FLOAT = 'f';
static final char TYPE_DOUBLE = 'd';
static final String LITERAL_TRUE = "true";
static final String LITERAL_FALSE = "false";
static final String NEWLINE = System.getProperty("line.separator", "\n");
static final char EOF = '\0';
private Tokens() {
}
/**
* Return if a character is a valid component in an identifier
* Return if a character is a valid component in an identifier.
*
* <p>An identifier character must match the expression {@code [a-zA-Z0-9_+.-]}</p>
*
@@ -73,8 +74,8 @@ package com.viaversion.viaversion.api.minecraft.nbt;
/**
* Return whether a character could be at some position in a number.
* <p>
* A string passing this check does not necessarily mean it is syntactically valid
*
* <p>A string passing this check does not necessarily mean it is syntactically valid.</p>
*
* @param c character to check
* @return if possibly part of a number
@@ -78,14 +78,18 @@ public interface ViaInjector {
*
* @return The name
*/
String getEncoderName();
default String getEncoderName() {
return "via-encoder";
}
/**
* Get the name of the decoder for then netty pipeline for this platform.
*
* @return The name
*/
String getDecoderName();
default String getDecoderName() {
return "via-decoder";
}
/**
* Get any relevant data for debugging injection issues.
@@ -87,49 +87,45 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
}
protected void registerClientboundChannelIdChanges() {
ClientboundPacketType[] newConstants = newClientboundPacketEnum.getEnumConstants();
Map<String, ClientboundPacketType> newClientboundPackets = new HashMap<>(newConstants.length);
for (ClientboundPacketType newConstant : newConstants) {
C2[] newConstants = newClientboundPacketEnum.getEnumConstants();
Map<String, C2> newClientboundPackets = new HashMap<>(newConstants.length);
for (C2 newConstant : newConstants) {
newClientboundPackets.put(newConstant.getName(), newConstant);
}
for (ClientboundPacketType packet : oldClientboundPacketEnum.getEnumConstants()) {
ClientboundPacketType mappedPacket = newClientboundPackets.get(packet.getName());
int oldId = packet.getId();
for (C1 packet : oldClientboundPacketEnum.getEnumConstants()) {
C2 mappedPacket = newClientboundPackets.get(packet.getName());
if (mappedPacket == null) {
// Packet doesn't exist on new client
Preconditions.checkArgument(hasRegisteredClientbound(State.PLAY, oldId),
Preconditions.checkArgument(hasRegisteredClientbound(packet),
"Packet " + packet + " in " + getClass().getSimpleName() + " has no mapping - it needs to be manually cancelled or remapped!");
continue;
}
int newId = mappedPacket.getId();
if (!hasRegisteredClientbound(State.PLAY, oldId)) {
registerClientbound(State.PLAY, oldId, newId);
if (!hasRegisteredClientbound(packet)) {
registerClientbound(packet, mappedPacket);
}
}
}
protected void registerServerboundChannelIdChanges() {
ServerboundPacketType[] oldConstants = oldServerboundPacketEnum.getEnumConstants();
Map<String, ServerboundPacketType> oldServerboundConstants = new HashMap<>(oldConstants.length);
for (ServerboundPacketType oldConstant : oldConstants) {
S1[] oldConstants = oldServerboundPacketEnum.getEnumConstants();
Map<String, S1> oldServerboundConstants = new HashMap<>(oldConstants.length);
for (S1 oldConstant : oldConstants) {
oldServerboundConstants.put(oldConstant.getName(), oldConstant);
}
for (ServerboundPacketType packet : newServerboundPacketEnum.getEnumConstants()) {
ServerboundPacketType mappedPacket = oldServerboundConstants.get(packet.getName());
int newId = packet.getId();
for (S2 packet : newServerboundPacketEnum.getEnumConstants()) {
S1 mappedPacket = oldServerboundConstants.get(packet.getName());
if (mappedPacket == null) {
// Packet doesn't exist on old server
Preconditions.checkArgument(hasRegisteredServerbound(State.PLAY, newId),
Preconditions.checkArgument(hasRegisteredServerbound(packet),
"Packet " + packet + " in " + getClass().getSimpleName() + " has no mapping - it needs to be manually cancelled or remapped!");
continue;
}
int oldId = mappedPacket.getId();
if (!hasRegisteredServerbound(State.PLAY, newId)) {
registerServerbound(State.PLAY, oldId, newId);
if (!hasRegisteredServerbound(packet)) {
registerServerbound(packet, mappedPacket);
}
}
}
@@ -158,6 +154,7 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
connection.addEntityTracker(this.getClass(), tracker);
}
@Override
public void registerServerbound(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper, boolean override) {
ProtocolPacket protocolPacket = new ProtocolPacket(state, oldPacketID, newPacketID, packetRemapper);
@@ -179,6 +176,11 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
});
}
@Override
public void cancelServerbound(State state, int newPacketID) {
cancelServerbound(state, -1, newPacketID);
}
@Override
public void cancelClientbound(State state, int oldPacketID, int newPacketID) {
registerClientbound(state, oldPacketID, newPacketID, new PacketRemapper() {
@@ -189,6 +191,11 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
});
}
@Override
public void cancelClientbound(State state, int oldPacketID) {
cancelClientbound(state, oldPacketID, -1);
}
@Override
public void registerClientbound(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper, boolean override) {
ProtocolPacket protocolPacket = new ProtocolPacket(state, oldPacketID, newPacketID, packetRemapper);
@@ -203,90 +210,120 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
@Override
public void registerClientbound(C1 packetType, @Nullable PacketRemapper packetRemapper) {
checkPacketType(packetType, packetType.getClass() == oldClientboundPacketEnum);
checkPacketType(packetType, oldClientboundPacketEnum == null || packetType.getClass() == oldClientboundPacketEnum);
ClientboundPacketType mappedPacket = oldClientboundPacketEnum == newClientboundPacketEnum ? packetType
C2 mappedPacket = oldClientboundPacketEnum == newClientboundPacketEnum ? (C2) packetType
: Arrays.stream(newClientboundPacketEnum.getEnumConstants()).filter(en -> en.getName().equals(packetType.getName())).findAny().orElse(null);
Preconditions.checkNotNull(mappedPacket, "Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " could not be automatically mapped!");
int oldId = packetType.getId();
int newId = mappedPacket.getId();
registerClientbound(State.PLAY, oldId, newId, packetRemapper);
registerClientbound(packetType, mappedPacket, packetRemapper);
}
@Override
public void registerClientbound(C1 packetType, @Nullable C2 mappedPacketType, @Nullable PacketRemapper packetRemapper) {
checkPacketType(packetType, packetType.getClass() == oldClientboundPacketEnum);
checkPacketType(mappedPacketType, mappedPacketType == null || mappedPacketType.getClass() == newClientboundPacketEnum);
registerClientbound(State.PLAY, packetType.getId(), mappedPacketType != null ? mappedPacketType.getId() : -1, packetRemapper);
public void registerClientbound(C1 packetType, @Nullable C2 mappedPacketType, @Nullable PacketRemapper packetRemapper, boolean override) {
register(clientbound, packetType, mappedPacketType, oldClientboundPacketEnum, newClientboundPacketEnum, packetRemapper, override);
}
@Override
public void cancelClientbound(C1 packetType) {
cancelClientbound(State.PLAY, packetType.getId(), packetType.getId());
registerClientbound(packetType, null, new PacketRemapper() {
@Override
public void registerMap() {
handler(PacketWrapper::cancel);
}
});
}
@Override
public void registerServerbound(S2 packetType, @Nullable PacketRemapper packetRemapper) {
checkPacketType(packetType, packetType.getClass() == newServerboundPacketEnum);
checkPacketType(packetType, newServerboundPacketEnum == null || packetType.getClass() == newServerboundPacketEnum);
ServerboundPacketType mappedPacket = oldServerboundPacketEnum == newServerboundPacketEnum ? packetType
S1 mappedPacket = oldServerboundPacketEnum == newServerboundPacketEnum ? (S1) packetType
: Arrays.stream(oldServerboundPacketEnum.getEnumConstants()).filter(en -> en.getName().equals(packetType.getName())).findAny().orElse(null);
Preconditions.checkNotNull(mappedPacket, "Packet type " + packetType + " in " + packetType.getClass().getSimpleName() + " could not be automatically mapped!");
int oldId = mappedPacket.getId();
int newId = packetType.getId();
registerServerbound(State.PLAY, oldId, newId, packetRemapper);
registerServerbound(packetType, mappedPacket, packetRemapper);
}
@Override
public void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType, @Nullable PacketRemapper packetRemapper) {
checkPacketType(packetType, packetType.getClass() == newServerboundPacketEnum);
checkPacketType(mappedPacketType, mappedPacketType == null || mappedPacketType.getClass() == oldServerboundPacketEnum);
registerServerbound(State.PLAY, mappedPacketType != null ? mappedPacketType.getId() : -1, packetType.getId(), packetRemapper);
public void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType, @Nullable PacketRemapper packetRemapper, boolean override) {
register(serverbound, packetType, mappedPacketType, newServerboundPacketEnum, oldServerboundPacketEnum, packetRemapper, override);
}
@Override
public void cancelServerbound(S2 packetType) {
Preconditions.checkArgument(packetType.getClass() == newServerboundPacketEnum);
cancelServerbound(State.PLAY, -1, packetType.getId());
registerServerbound(packetType, null, new PacketRemapper() {
@Override
public void registerMap() {
handler(PacketWrapper::cancel);
}
});
}
private void register(Map<Packet, ProtocolPacket> packetMap, PacketType packetType, @Nullable PacketType mappedPacketType,
Class<? extends PacketType> unmappedPacketEnum, Class<? extends PacketType> mappedPacketEnum,
@Nullable PacketRemapper remapper, boolean override) {
checkPacketType(packetType, unmappedPacketEnum == null || packetType.getClass() == unmappedPacketEnum);
checkPacketType(mappedPacketType, mappedPacketType == null || mappedPacketEnum == null || mappedPacketType.getClass() == mappedPacketEnum);
Preconditions.checkArgument(mappedPacketType == null || packetType.state() == mappedPacketType.state(), "Packet type state does not match mapped packet type state");
ProtocolPacket protocolPacket = new ProtocolPacket(packetType.state(), packetType, mappedPacketType, remapper);
Packet packet = new Packet(packetType.state(), packetType.getId());
if (!override && packetMap.containsKey(packet)) {
Via.getPlatform().getLogger().log(Level.WARNING, packet + " already registered!" +
" If override is intentional, set override to true. Stacktrace: ", new Exception());
}
packetMap.put(packet, protocolPacket);
}
@Override
public boolean hasRegisteredClientbound(State state, int oldPacketID) {
Packet packet = new Packet(state, oldPacketID);
public boolean hasRegisteredClientbound(C1 packetType) {
return hasRegisteredClientbound(packetType.state(), packetType.getId());
}
@Override
public boolean hasRegisteredServerbound(S2 packetType) {
return hasRegisteredServerbound(packetType.state(), packetType.getId());
}
@Override
public boolean hasRegisteredClientbound(State state, int unmappedPacketId) {
Packet packet = new Packet(state, unmappedPacketId);
return clientbound.containsKey(packet);
}
@Override
public boolean hasRegisteredServerbound(State state, int newPacketId) {
Packet packet = new Packet(state, newPacketId);
public boolean hasRegisteredServerbound(State state, int unmappedPacketId) {
Packet packet = new Packet(state, unmappedPacketId);
return serverbound.containsKey(packet);
}
@Override
public void transform(Direction direction, State state, PacketWrapper packetWrapper) throws Exception {
Packet statePacket = new Packet(state, packetWrapper.getId());
Map<Packet, ProtocolPacket> packetMap = (direction == Direction.CLIENTBOUND ? clientbound : serverbound);
Map<Packet, ProtocolPacket> packetMap = direction == Direction.CLIENTBOUND ? clientbound : serverbound;
ProtocolPacket protocolPacket = packetMap.get(statePacket);
if (protocolPacket == null) {
return;
}
// Write packet id
int oldId = packetWrapper.getId();
int newId = direction == Direction.CLIENTBOUND ? protocolPacket.getNewID() : protocolPacket.getOldID();
packetWrapper.setId(newId);
int unmappedId = packetWrapper.getId();
if (protocolPacket.isMappedOverTypes()) {
packetWrapper.setPacketType(protocolPacket.getMappedPacketType());
} else {
int mappedId = direction == Direction.CLIENTBOUND ? protocolPacket.getNewId() : protocolPacket.getOldId();
if (unmappedId != mappedId) {
packetWrapper.setId(mappedId);
}
}
PacketRemapper remapper = protocolPacket.getRemapper();
if (remapper != null) {
try {
remapper.remap(packetWrapper);
} catch (InformativeException e) { // Catch InformativeExceptions, pass through CancelExceptions
throwRemapError(direction, state, oldId, newId, e);
throwRemapError(direction, state, unmappedId, packetWrapper.getId(), e);
return;
}
@@ -390,14 +427,34 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
public static final class ProtocolPacket {
private final State state;
private final int oldID;
private final int newID;
private final int oldId;
private final int newId;
private final PacketType unmappedPacketType;
private final PacketType mappedPacketType;
private final PacketRemapper remapper;
public ProtocolPacket(State state, int oldID, int newID, @Nullable PacketRemapper remapper) {
@Deprecated
public ProtocolPacket(State state, int oldId, int newId, @Nullable PacketRemapper remapper) {
this.state = state;
this.oldID = oldID;
this.newID = newID;
this.oldId = oldId;
this.newId = newId;
this.remapper = remapper;
this.unmappedPacketType = null;
this.mappedPacketType = null;
}
public ProtocolPacket(State state, PacketType unmappedPacketType, @Nullable PacketType mappedPacketType, @Nullable PacketRemapper remapper) {
this.state = state;
this.unmappedPacketType = unmappedPacketType;
if (unmappedPacketType.direction() == Direction.CLIENTBOUND) {
this.oldId = unmappedPacketType.getId();
this.newId = mappedPacketType != null ? mappedPacketType.getId() : -1;
} else {
// Serverbound switcheroo in old vs. new id caused issues and was counterintuitive
this.oldId = mappedPacketType != null ? mappedPacketType.getId() : -1;
this.newId = unmappedPacketType.getId();
}
this.mappedPacketType = mappedPacketType;
this.remapper = remapper;
}
@@ -405,12 +462,40 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
return state;
}
public int getOldID() {
return oldID;
@Deprecated
public int getOldId() {
return oldId;
}
public int getNewID() {
return newID;
@Deprecated
public int getNewId() {
return newId;
}
/**
* Returns the unmapped packet type, or null if mapped over ids.
* This is NOT the same as calling {@link #getOldId()} (think of unmapped vs. old in 1.17→1.16).
*
* @return unmapped packet type, or null if mapped over ids
*/
@Nullable
public PacketType getUnmappedPacketType() {
return unmappedPacketType;
}
/**
* Returns the mapped packet type, or null if mapped over ids or mapped to no packet type.
* This is NOT the same as calling {@link #getNewId()} (think of mapped vs. new in 1.17→1.16).
*
* @return new packet type, or null if mapped over ids or mapped to no packet type
*/
@Nullable
public PacketType getMappedPacketType() {
return mappedPacketType;
}
public boolean isMappedOverTypes() {
return unmappedPacketType != null;
}
@Nullable
@@ -47,68 +47,64 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*/
public interface Protocol<C1 extends ClientboundPacketType, C2 extends ClientboundPacketType, S1 extends ServerboundPacketType, S2 extends ServerboundPacketType> {
/**
* Register a serverbound packet, with simple id transformation.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
*/
default void registerServerbound(State state, int oldPacketID, int newPacketID) {
registerServerbound(state, oldPacketID, newPacketID, null);
}
/**
* Register a serverbound packet, with id transformation and remapper.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
* @param packetRemapper The remapper to use for the packet
*/
default void registerServerbound(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper) {
registerServerbound(state, oldPacketID, newPacketID, packetRemapper, false);
}
/**
* Registers a serverbound packet, with id transformation and remapper.
*
* @param state state which the packet is sent in.
* @param oldPacketID old packet ID
* @param newPacketID new packet ID
* @param packetRemapper remapper to use for the packet
* @param override whether an existing mapper should be overridden
* @see #registerServerbound(ServerboundPacketType, ServerboundPacketType, PacketRemapper, boolean)
*/
void registerServerbound(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper, boolean override);
/**
* @deprecated use {@link #cancelServerbound(State, int)}
*/
@Deprecated/*(forRemoval = true)*/
void cancelServerbound(State state, int oldPacketID, int newPacketID);
default void cancelServerbound(State state, int newPacketID) {
cancelServerbound(state, -1, newPacketID);
}
void cancelServerbound(State state, int newPacketID);
/**
* Register a clientbound packet, with simple id transformation.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
*/
default void registerClientbound(State state, int oldPacketID, int newPacketID) {
registerClientbound(state, oldPacketID, newPacketID, null);
}
/**
* Register a clientbound packet, with id transformation and remapper.
*
* @param state The state which the packet is sent in.
* @param oldPacketID The old packet ID
* @param newPacketID The new packet ID
* @param packetRemapper The remapper to use for the packet
*/
default void registerClientbound(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper) {
registerClientbound(state, oldPacketID, newPacketID, packetRemapper, false);
}
/**
* @deprecated use {@link #cancelClientbound(State, int)}
*/
@Deprecated/*(forRemoval = true)*/
void cancelClientbound(State state, int oldPacketID, int newPacketID);
default void cancelClientbound(State state, int oldPacketID) {
cancelClientbound(state, oldPacketID, -1);
}
void cancelClientbound(State state, int oldPacketID);
/**
* Registers a clientbound packet, with id transformation and remapper.
*
* @param state state which the packet is sent in.
* @param oldPacketID old packet ID
* @param newPacketID new packet ID
* @param packetRemapper remapper to use for the packet
* @param override whether an existing mapper should be overridden
* @see #registerClientbound(ClientboundPacketType, ClientboundPacketType, PacketRemapper, boolean)
*/
void registerClientbound(State state, int oldPacketID, int newPacketID, PacketRemapper packetRemapper, boolean override);
// ---------------------------------------------------------------------------------------
/**
* Registers a clientbound protocol and automatically maps it to the new id.
*
@@ -117,15 +113,6 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
*/
void registerClientbound(C1 packetType, @Nullable PacketRemapper packetRemapper);
/**
* Registers a clientbound protocol.
*
* @param packetType clientbound packet type the server initially sends
* @param mappedPacketType clientbound packet type after transforming for the client
* @param packetRemapper remapper
*/
void registerClientbound(C1 packetType, C2 mappedPacketType, @Nullable PacketRemapper packetRemapper);
/**
* Maps a packet type to another packet type without a packet handler.
* Note that this should not be called for simple channel mappings of the same packet; this is already done automatically.
@@ -137,6 +124,27 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
registerClientbound(packetType, mappedPacketType, null);
}
/**
* Registers a clientbound packet mapping.
*
* @param packetType clientbound packet type the server initially sends
* @param mappedPacketType clientbound packet type after transforming for the client
* @param packetRemapper remapper
*/
default void registerClientbound(C1 packetType, @Nullable C2 mappedPacketType, @Nullable PacketRemapper packetRemapper) {
registerClientbound(packetType, mappedPacketType, packetRemapper, false);
}
/**
* Registers a clientbound packet mapping.
*
* @param packetType clientbound packet type the server initially sends
* @param mappedPacketType clientbound packet type after transforming for the client
* @param packetRemapper remapper
* @param override whether an existing mapping should be overridden if present
*/
void registerClientbound(C1 packetType, @Nullable C2 mappedPacketType, @Nullable PacketRemapper packetRemapper, boolean override);
/**
* Cancels any clientbound packets from the given type.
*
@@ -144,6 +152,17 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
*/
void cancelClientbound(C1 packetType);
/**
* Maps a packet type to another packet type without a packet handler.
* Note that this should not be called for simple channel mappings of the same packet; this is already done automatically.
*
* @param packetType serverbound packet type the client initially sends
* @param mappedPacketType serverbound packet type after transforming for the client
*/
default void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType) {
registerServerbound(packetType, mappedPacketType, null);
}
/**
* Registers a serverbound protocol and automatically maps it to the server's id.
*
@@ -159,7 +178,19 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
* @param mappedPacketType serverbound packet type after transforming for the server
* @param packetRemapper remapper
*/
void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType, @Nullable PacketRemapper packetRemapper);
default void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType, @Nullable PacketRemapper packetRemapper) {
registerServerbound(packetType, mappedPacketType, packetRemapper, false);
}
/**
* Registers a serverbound packet mapping.
*
* @param packetType serverbound packet type initially sent by the client
* @param mappedPacketType serverbound packet type after transforming for the server
* @param packetRemapper remapper
* @param override whether an existing mapping should be overridden if present
*/
void registerServerbound(S2 packetType, @Nullable S1 mappedPacketType, @Nullable PacketRemapper packetRemapper, boolean override);
/**
* Cancels any serverbound packets from the given type.
@@ -168,23 +199,40 @@ public interface Protocol<C1 extends ClientboundPacketType, C2 extends Clientbou
*/
void cancelServerbound(S2 packetType);
/**
* Checks if a clientbound packet has already been registered.
*
* @param state state which the packet is sent in
* @param oldPacketID old packet ID
* @param packetType clientbound packet type
* @return true if already registered
*/
boolean hasRegisteredClientbound(State state, int oldPacketID);
boolean hasRegisteredClientbound(C1 packetType);
/**
* Checks if a serverbound packet has already been registered.
*
* @param state state which the packet is sent in
* @param newPacketId packet ID
* @param packetType serverbound packet type
* @return true if already registered
*/
boolean hasRegisteredServerbound(State state, int newPacketId);
boolean hasRegisteredServerbound(S2 packetType);
/**
* Checks if a clientbound packet has already been registered.
*
* @param state state which the packet is sent in
* @param oldPacketId old packet id
* @return true if already registered
*/
boolean hasRegisteredClientbound(State state, int oldPacketId);
/**
* Checks if a serverbound packet has already been registered.
*
* @param state state which the packet is sent in
* @param unmappedPacketId new packet id
* @return true if already registered
*/
boolean hasRegisteredServerbound(State state, int unmappedPacketId);
/**
* Transform a packet using this protocol
@@ -24,8 +24,11 @@ package com.viaversion.viaversion.api.protocol;
import com.google.common.collect.Range;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.VersionedPacketTransformer;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion;
import io.netty.buffer.ByteBuf;
@@ -143,6 +146,36 @@ public interface ProtocolManager {
*/
@Nullable List<ProtocolPathEntry> getProtocolPath(int clientVersion, int serverVersion);
/**
* Returns a versioned packet transformer to transform and send packets from a given base version to any client version supported by Via.
* The used packet types have to match the given protocol version.
* <p>
* It is important the correct packet type classes are passed. The ViaVersion given packet type enums
* are found in the common module. Examples for correct invocations are:
* <pre>
* createPacketTransformer(ProtocolVersion.v1_17_1, ClientboundPackets1_17_1.class, ServerboundPackets1_17.class);
* createPacketTransformer(ProtocolVersion.v1_12_2, ClientboundPackets1_12_1.class, ServerboundPackets1_12_1.class);
* createPacketTransformer(ProtocolVersion.v1_8, ClientboundPackets1_8.class, ServerboundPackets1_8.class);
* </pre>
* If only clientbound <b>or</b> serverbound packets are used, the other class can be passed as null, see:
* <pre>
* VersionedPacketTransformer&lt;?, ServerboundHandshakePackets&gt; creator
* = createPacketTransformer(ProtocolVersion.v1_17_1, null, ServerboundHandshakePackets.class);
* </pre>
*
* @param inputVersion input protocol version
* @param clientboundPacketsClass clientbound packets class, or null if no clientbound packets will be sent or transformed with this
* @param serverboundPacketsClass serverbound packets class, or null if no serverbound packets will be sent or transformed with this
* @return versioned packet transformer to transform and send packets from a given protocol version
* @throws IllegalArgumentException if either of the packet classes are the base {@link ClientboundPacketType} or {@link ServerboundPacketType} interfaces
* @throws IllegalArgumentException if both packet classes are null
*/
<C extends ClientboundPacketType,
S extends ServerboundPacketType
> VersionedPacketTransformer<C, S> createPacketTransformer(ProtocolVersion inputVersion,
@Nullable Class<C> clientboundPacketsClass,
@Nullable Class<S> serverboundPacketsClass);
/**
* Returns whether protocol path calculation expects the path to come closer to the expected version with each entry, true by default.
* <p>
@@ -248,11 +281,23 @@ public interface ProtocolManager {
/**
* Creates a new packet wrapper instance.
*
* @param packetId packet id
* @param packetType packet type, or null if none should be written to the packet (raw id = -1)
* @param buf input buffer
* @param connection user connection
* @return new packet wrapper instance
* @see PacketWrapper#create(PacketType, ByteBuf, UserConnection)
*/
PacketWrapper createPacketWrapper(@Nullable PacketType packetType, @Nullable ByteBuf buf, UserConnection connection);
/**
* Creates a new packet wrapper instance.
*
* @param packetId packet id
* @param buf input buffer
* @param connection user connection
* @return new packet wrapper instance
* @deprecated magic id; prefer using {@link #createPacketWrapper(PacketType, ByteBuf, UserConnection)}
*/
@Deprecated
PacketWrapper createPacketWrapper(int packetId, @Nullable ByteBuf buf, UserConnection connection);
}
@@ -26,16 +26,26 @@ public interface ProtocolPathEntry {
/**
* Returns the resulting protocol after transformation using
* the {@link #getProtocol()} protocol handlers.
* the {@link #protocol()} protocol handlers.
*
* @return output protocol version after transformation
*/
int getOutputProtocolVersion();
int outputProtocolVersion();
/**
* Returns the protocol to be applied with this entry.
*
* @return protocol to be applied with this entry
*/
Protocol getProtocol();
Protocol<?, ?, ?, ?> protocol();
@Deprecated/*(forRemoval = true)*/
default int getOutputProtocolVersion() {
return outputProtocolVersion();
}
@Deprecated/*(forRemoval = true)*/
default Protocol getProtocol() {
return protocol();
}
}
@@ -29,12 +29,22 @@ public interface ProtocolPathKey {
*
* @return client protocol version
*/
int getClientProtocolVersion();
int clientProtocolVersion();
/**
* Returns the server protocol version.
*
* @return server protocol version
*/
int getServerProtocolVersion();
int serverProtocolVersion();
@Deprecated/*(forRemoval = true)*/
default int getClientProtocolVersion() {
return clientProtocolVersion();
}
@Deprecated/*(forRemoval = true)*/
default int getServerProtocolVersion() {
return serverProtocolVersion();
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
/**
@@ -45,5 +46,10 @@ public interface SimpleProtocol extends Protocol<SimpleProtocol.DummyPacketTypes
public String getName() {
return name();
}
@Override
public Direction direction() {
throw new UnsupportedOperationException();
}
}
}
@@ -27,4 +27,9 @@ package com.viaversion.viaversion.api.protocol.packet;
* representing PLAY state packets, ordered by their packet id.
*/
public interface ClientboundPacketType extends PacketType {
@Override
default Direction direction() {
return Direction.CLIENTBOUND;
}
}
@@ -43,4 +43,20 @@ public interface PacketType {
* @return name of the packet
*/
String getName();
/**
* Clientbound or serverbound direction.
*
* @return direction
*/
Direction direction();
/**
* Returns the protocol state the packet belongs to.
*
* @return protocol state
*/
default State state() {
return State.PLAY;
}
}
@@ -41,34 +41,36 @@ public interface PacketWrapper {
/**
* Creates a new packet wrapper instance.
*
* @param packetType packet
* @param packetType packet type, or null if none should be written to the buffer (raw id = -1)
* @param connection user connection
* @return new packet wrapper
*/
static PacketWrapper create(PacketType packetType, UserConnection connection) {
return create(packetType.getId(), null, connection);
static PacketWrapper create(@Nullable PacketType packetType, UserConnection connection) {
return create(packetType, null, connection);
}
/**
* Creates a new packet wrapper instance.
*
* @param packetType packet type
* @param packetType packet type, or null if none should be written to the buffer (raw id = -1)
* @param inputBuffer input buffer
* @param connection user connection
* @return new packet wrapper
*/
static PacketWrapper create(PacketType packetType, @Nullable ByteBuf inputBuffer, UserConnection connection) {
return create(packetType.getId(), inputBuffer, connection);
static PacketWrapper create(@Nullable PacketType packetType, @Nullable ByteBuf inputBuffer, UserConnection connection) {
return Via.getManager().getProtocolManager().createPacketWrapper(packetType, inputBuffer, connection);
}
/**
* Creates a new packet wrapper instance.
*
* @param packetId packet id
* @param packetId packet id, or -1 if none should be written to the buffer
* @param inputBuffer input buffer
* @param connection user connection
* @return new packet wrapper
* @deprecated magic id; prefer using {@link #create(PacketType, ByteBuf, UserConnection)}
*/
@Deprecated
static PacketWrapper create(int packetId, @Nullable ByteBuf inputBuffer, UserConnection connection) {
return Via.getManager().getProtocolManager().createPacketWrapper(packetId, inputBuffer, connection);
}
@@ -218,15 +220,28 @@ public interface PacketWrapper {
ChannelFuture sendFuture(Class<? extends Protocol> packetProtocol) throws Exception;
/**
* Send this packet to the associated user.
* Be careful not to send packets twice.
* (Sends it after current)
* <b>This method is no longer used, it's favoured to use {@link #send(Class)} as it will handle the pipeline properly.</b>
* @deprecated misleading; use {@link #sendRaw()}. This method will be removed in 5.0.0
*/
@Deprecated/*(forRemoval = true)*/
default void send() throws Exception {
sendRaw();
}
/**
* Sends this packet to the connection.
* <b>Unlike {@link #send(Class)}, this method does not handle the pipeline with packet id and data changes.</b>
*
* @throws Exception if it fails to write
*/
@Deprecated
void send() throws Exception;
void sendRaw() throws Exception;
/**
* Sends this packet to the associated user, submitted to netty's event loop.
* <b>Unlike {@link #send(Class)}, this method does not handle the pipeline with packet id and data changes.</b>
*
* @throws Exception if it fails to write
*/
void scheduleSendRaw() throws Exception;
/**
* Creates a new packet for the target of this packet.
@@ -315,9 +330,28 @@ public interface PacketWrapper {
* (Ensure the ID is suitable for viaversion)
*
* @throws Exception If it failed to write
* @deprecated misleading; use {@link #sendToServerRaw()}. This method will be removed in 5.0.0
*/
@Deprecated
void sendToServer() throws Exception;
@Deprecated/*(forRemoval = true)*/
default void sendToServer() throws Exception {
sendToServerRaw();
}
/**
* Sends this packet to the server.
* <b>Unlike {@link #sendToServer(Class)}, this method does not handle the pipeline with packet id and data changes.</b>
*
* @throws Exception if it fails to write
*/
void sendToServerRaw() throws Exception;
/**
* Sends this packet to the server, submitted to netty's event loop.
* <b>Unlike {@link #sendToServer(Class)}, this method does not handle the pipeline with packet id and data changes.</b>
*
* @throws Exception if it fails to write
*/
void scheduleSendToServerRaw() throws Exception;
/**
* Send this packet to the server on the current thread, skipping the current protocol.
@@ -358,25 +392,45 @@ public interface PacketWrapper {
void scheduleSendToServer(Class<? extends Protocol> protocol, boolean skipCurrentPipeline) throws Exception;
/**
* Returns the packet id.
* Returns the packet type.
* Currently only non-null for manually constructed packets before transformation.
*
* @return packet id
* @return packet type if set
*/
@Nullable PacketType getPacketType();
/**
* Sets the packet type. If set to null, it will not be written to the buffer with {@link #writeToBuffer(ByteBuf)}.
* Setting the type to null also sets the raw packet id to -1.
*
* @param packetType packet type
*/
void setPacketType(@Nullable PacketType packetType);
/**
* Returns the raw packet id.
*
* @return raw packet id
*/
int getId();
/**
* Sets the packet id. If set to -1, it will not be written to the buffer with {@link #writeToBuffer(ByteBuf)}.
* Sets the packet type.
*
* @param packetType packet type
* @deprecated use {@link #setPacketType(PacketType)}. This method will be removed in 5.0.0
*/
@Deprecated/*(forRemoval = true)*/
default void setId(PacketType packetType) {
setId(packetType.getId());
setPacketType(packetType);
}
/**
* Sets the packet id. If set to -1, it will not be written to the buffer with {@link #writeToBuffer(ByteBuf)}.
*
* @param id packet id
* @deprecated magic id, loses packet type info; use {@link #setPacketType(PacketType)}
*/
@Deprecated
void setId(int id);
}
@@ -27,4 +27,9 @@ package com.viaversion.viaversion.api.protocol.packet;
* representing PLAY state packets, ordered by their packet id.
*/
public interface ServerboundPacketType extends PacketType {
@Override
default Direction direction() {
return Direction.SERVERBOUND;
}
}
@@ -0,0 +1,106 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.protocol.packet;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.function.Consumer;
/**
* Utility to send packets from a given base version to or from any client version supported by Via.
*
* @param <C> clientbound packet type
* @param <S> serverbound packet type
*/
public interface VersionedPacketTransformer<C extends ClientboundPacketType, S extends ServerboundPacketType> {
/**
* Sends a packet to the user or server, depending on the packet type given by {@link PacketWrapper#getPacketType()}.
* Returns false if the packet has been cancelled at some point, but does not indicate whether a replacement has been constructed.
*
* @return whether this packet specifically has been sent, false if cancelled
* @throws IllegalArgumentException if the packet type is not of the expected clientbound or serverbound packets class
* @throws IllegalArgumentException if {@link PacketWrapper#user()} returns null
* @throws RuntimeException if no path from the input version to the required client version exists
* @throws Exception if an error occurred while transforming or sending the packet
*/
boolean send(PacketWrapper packet) throws Exception;
/**
* @see #send(PacketWrapper)
*/
boolean send(UserConnection connection, C packetType, Consumer<PacketWrapper> packetWriter) throws Exception;
/**
* @see #send(PacketWrapper)
*/
boolean send(UserConnection connection, S packetType, Consumer<PacketWrapper> packetWriter) throws Exception;
/**
* Sends a packet to the user or server, depending on the packet type given by {@link PacketWrapper#getPacketType()}, submitted to the netty event loop.
* Returns false if the packet has been cancelled at some point, but does not indicate whether a replacement has been constructed.
*
* @param packet packet wrapper
* @return whether this packet specifically has been sent, false if cancelled
* @throws IllegalArgumentException if the packet type is not of the expected clientbound or serverbound packets class
* @throws IllegalArgumentException if {@link PacketWrapper#user()} returns null
* @throws RuntimeException if no path from the input version to the required client version exists
* @throws Exception if an error occurred while transforming or sending the packet
*/
boolean scheduleSend(PacketWrapper packet) throws Exception;
/**
* @see #scheduleSend(PacketWrapper)
*/
boolean scheduleSend(UserConnection connection, C packetType, Consumer<PacketWrapper> packetWriter) throws Exception;
/**
* @see #scheduleSend(PacketWrapper)
*/
boolean scheduleSend(UserConnection connection, S packetType, Consumer<PacketWrapper> packetWriter) throws Exception;
/**
* Transforms a packet to the protocol version of the given connection or server, or null if cancelled at some point.
* The target version is given by {@link ProtocolInfo#getProtocolVersion()} or {@link ProtocolInfo#getServerProtocolVersion()}.
*
* @param packet packet wrapper
* @return created and transformed packet wrapper, or null if cancelled at some point
* @throws IllegalArgumentException if the packet type is not of the expected clientbound or serverbound packets class
* @throws IllegalArgumentException if {@link PacketWrapper#user()} returns null
* @throws RuntimeException if no path from the input version to the required client version exists
* @throws Exception if an error occurred while transforming the packet
*/
@Nullable PacketWrapper transform(PacketWrapper packet) throws Exception;
/**
* @see #transform(PacketWrapper)
*/
@Nullable PacketWrapper transform(UserConnection connection, C packetType, Consumer<PacketWrapper> packetWriter) throws Exception;
/**
* @see #transform(PacketWrapper)
*/
@Nullable PacketWrapper transform(UserConnection connection, S packetType, Consumer<PacketWrapper> packetWriter) throws Exception;
}
@@ -20,41 +20,38 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
package com.viaversion.viaversion.api.protocol.version;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.ArrayList;
import java.util.List;
public class Chunk1_8 extends BaseChunk {
private boolean unloadPacket;
public Chunk1_8(int x, int z, boolean groundUp, int bitmask, ChunkSection[] sections, int[] biomeData, List<CompoundTag> blockEntities) {
super(x, z, groundUp, false, bitmask, sections, biomeData, blockEntities);
}
public interface BlockedProtocolVersions {
/**
* Chunk unload.
* Returns whether the given protocol version is blocked per boundary ranges or individually blocked versions.
*
* @param x coord
* @param z coord
* @param protocolVersion protocol version
* @return whether the given protocol version is blocked
*/
public Chunk1_8(int x, int z) {
this(x, z, true, 0, new ChunkSection[16], null, new ArrayList<>());
this.unloadPacket = true;
}
boolean contains(int protocolVersion);
/**
* Does this chunks have biome data
* Returns the boundary below which protocol versions are blocked, or -1 if none is set.
*
* @return True if the chunks has biome data
* @return exclusive boundary below which protocol versions are blocked, or -1 if none
*/
public boolean hasBiomeData() {
return biomeData != null && fullChunk;
}
int blocksBelow();
public boolean isUnloadPacket() {
return unloadPacket;
}
/**
* Returns the boundary above which protocol versions are blocked, or -1 if none is set.
*
* @return exclusive boundary above which protocol versions are blocked, or -1 if none
*/
int blocksAbove();
/**
* Returns a set of blocked protocol versions between the outer block ranges.
*
* @return set of blocked protocol versions between the outer block ranges
*/
IntSet singleBlockedVersions();
}
@@ -77,6 +77,8 @@ public class ProtocolVersion {
public static final ProtocolVersion v1_16_3 = register(753, "1.16.3");
public static final ProtocolVersion v1_16_4 = register(754, "1.16.4/5", new VersionRange("1.16", 4, 5));
public static final ProtocolVersion v1_17 = register(755, "1.17");
public static final ProtocolVersion v1_17_1 = register(756, "1.17.1");
public static final ProtocolVersion v1_18 = register(757, "1.18");
public static final ProtocolVersion unknown = register(-1, "UNKNOWN");
public static ProtocolVersion register(int version, String name) {
@@ -214,12 +216,12 @@ public class ProtocolVersion {
Preconditions.checkArgument(!versionWildcard || versionRange == null, "A version cannot be a wildcard and a range at the same time!");
if (versionRange != null) {
includedVersions = new LinkedHashSet<>();
for (int i = versionRange.getRangeFrom(); i <= versionRange.getRangeTo(); i++) {
for (int i = versionRange.rangeFrom(); i <= versionRange.rangeTo(); i++) {
if (i == 0) {
includedVersions.add(versionRange.getBaseVersion()); // Keep both the base version and with ".0" appended
includedVersions.add(versionRange.baseVersion()); // Keep both the base version and with ".0" appended
}
includedVersions.add(versionRange.getBaseVersion() + "." + i);
includedVersions.add(versionRange.baseVersion() + "." + i);
}
} else {
includedVersions = Collections.singleton(name);
@@ -35,7 +35,7 @@ public interface ServerProtocolVersion {
int lowestSupportedVersion();
/**
* Returns the lowest supported protocol version by this server.
* Returns the highest supported protocol version by this server.
* This and {@link #lowestSupportedVersion()} should only differ on proxy servers supporting multiple versions.
*
* @return highest supported protocol version
@@ -50,7 +50,7 @@ public class VersionRange {
*
* @return major version name
*/
public String getBaseVersion() {
public String baseVersion() {
return baseVersion;
}
@@ -59,7 +59,7 @@ public class VersionRange {
*
* @return lowest included minor version
*/
public int getRangeFrom() {
public int rangeFrom() {
return rangeFrom;
}
@@ -68,6 +68,21 @@ public class VersionRange {
*
* @return highest included minor version
*/
public int rangeTo() {
return rangeTo;
}
@Deprecated/*(forRemoval = true)*/
public String getBaseVersion() {
return baseVersion;
}
@Deprecated/*(forRemoval = true)*/
public int getRangeFrom() {
return rangeFrom;
}
@Deprecated/*(forRemoval = true)*/
public int getRangeTo() {
return rangeTo;
}
@@ -32,17 +32,22 @@ public abstract class PartialType<T, X> extends Type<T> {
this.param = param;
}
protected PartialType(X param, String name, Class<T> type) {
super(name, type);
this.param = param;
}
public abstract T read(ByteBuf buffer, X param) throws Exception;
public abstract void write(ByteBuf buffer, X param, T object) throws Exception;
@Override
public T read(ByteBuf buffer) throws Exception {
public final T read(ByteBuf buffer) throws Exception {
return read(buffer, this.param);
}
@Override
public void write(ByteBuf buffer, T object) throws Exception {
public final void write(ByteBuf buffer, T object) throws Exception {
write(buffer, this.param, object);
}
}
@@ -31,17 +31,26 @@ public class ByteType extends Type<Byte> implements TypeConverter<Byte> {
super(Byte.class);
}
public byte readPrimitive(ByteBuf buffer) {
return buffer.readByte();
}
public void writePrimitive(ByteBuf buffer, byte object) {
buffer.writeByte(object);
}
@Override
@Deprecated
public Byte read(ByteBuf buffer) {
return buffer.readByte();
}
@Override
@Deprecated
public void write(ByteBuf buffer, Byte object) {
buffer.writeByte(object);
}
@Override
public Byte from(Object o) {
if (o instanceof Number) {
@@ -24,12 +24,13 @@ package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.type.Type;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Particle {
private List<ParticleData> arguments = new ArrayList<>(4);
private int id;
private List<ParticleData> arguments = new LinkedList<>();
public Particle(int id) {
this.id = id;
@@ -47,10 +48,15 @@ public class Particle {
return arguments;
}
@Deprecated/*(forRemoval = true)*/
public void setArguments(List<ParticleData> arguments) {
this.arguments = arguments;
}
public <T> void add(Type<T> type, T value) {
arguments.add(new ParticleData(type, value));
}
public static class ParticleData {
private Type type;
private Object value;
@@ -0,0 +1,116 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.minecraft;
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.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@Deprecated/*(forRemoval = true)*/
public abstract class AbstractParticleType extends Type<Particle> {
protected final Int2ObjectMap<ParticleReader> readers = new Int2ObjectOpenHashMap<>();
protected AbstractParticleType() {
super("Particle", Particle.class);
}
@Override
public void write(ByteBuf buffer, Particle object) throws Exception {
Type.VAR_INT.writePrimitive(buffer, object.getId());
for (Particle.ParticleData data : object.getArguments()) {
data.getType().write(buffer, data.getValue());
}
}
@Override
public Particle read(ByteBuf buffer) throws Exception {
int type = Type.VAR_INT.readPrimitive(buffer);
Particle particle = new Particle(type);
ParticleReader reader = readers.get(type);
if (reader != null) {
reader.read(buffer, particle);
}
return particle;
}
protected ParticleReader blockHandler() {
return (buf, particle) -> {
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buf))); // Flat Block
};
}
protected ParticleReader itemHandler(Type<Item> itemType) {
return (buf, particle) -> {
particle.getArguments().add(new Particle.ParticleData(itemType, itemType.read(buf))); // Flat item;
};
}
protected ParticleReader dustHandler() {
return (buf, particle) -> {
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Red 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Green 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Blue 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Scale 0.01 - 4
};
}
protected ParticleReader dustTransitionHandler() {
return (buf, particle) -> {
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Red 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Green 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Blue 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Scale 0.01 - 4
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Red
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Green
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buf))); // Blue
};
}
protected ParticleReader vibrationHandler(Type<Position> positionType) {
return (buf, particle) -> {
particle.getArguments().add(new Particle.ParticleData(positionType, positionType.read(buf))); // From block pos
String resourceLocation = Type.STRING.read(buf);
if (resourceLocation.equals("block")) {
particle.getArguments().add(new Particle.ParticleData(positionType, positionType.read(buf))); // Target block pos
} else if (resourceLocation.equals("entity")) {
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buf))); // Target entity
} else {
Via.getPlatform().getLogger().warning("Unknown vibration path position source type: " + resourceLocation);
}
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buf))); // Arrival in ticks
};
}
@FunctionalInterface
public interface ParticleReader {
void read(ByteBuf buf, Particle particle) throws Exception;
}
}
@@ -20,15 +20,23 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.minecraft.ModernMetaListType;
public class MetadataList1_12Type extends ModernMetaListType {
public abstract class BaseChunkBulkType extends Type<Chunk[]> {
protected BaseChunkBulkType() {
super(Chunk[].class);
}
protected BaseChunkBulkType(String typeName) {
super(typeName, Chunk[].class);
}
@Override
protected Type<Metadata> getType() {
return Types1_12.METADATA;
public Class<? extends Type> getBaseClass() {
return BaseChunkBulkType.class;
}
}
@@ -42,8 +42,8 @@ public class EulerAngleType extends Type<EulerAngle> {
@Override
public void write(ByteBuf buffer, EulerAngle object) throws Exception {
Type.FLOAT.writePrimitive(buffer, object.getX());
Type.FLOAT.writePrimitive(buffer, object.getY());
Type.FLOAT.writePrimitive(buffer, object.getZ());
Type.FLOAT.writePrimitive(buffer, object.x());
Type.FLOAT.writePrimitive(buffer, object.y());
Type.FLOAT.writePrimitive(buffer, object.z());
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
@@ -29,16 +30,20 @@ import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractMetaListType extends MetaListTypeTemplate {
protected abstract Type<Metadata> getType();
public final class MetaListType extends MetaListTypeTemplate {
private final Type<Metadata> type;
public MetaListType(Type<Metadata> type) {
Preconditions.checkNotNull(type);
this.type = type;
}
@Override
public List<Metadata> read(final ByteBuf buffer) throws Exception {
final Type<Metadata> type = this.getType();
final List<Metadata> list = new ArrayList<>();
Metadata meta;
do {
meta = type.read(buffer);
meta = this.type.read(buffer);
if (meta != null) {
list.add(meta);
}
@@ -48,14 +53,9 @@ public abstract class AbstractMetaListType extends MetaListTypeTemplate {
@Override
public void write(final ByteBuf buffer, final List<Metadata> object) throws Exception {
final Type<Metadata> type = this.getType();
for (final Metadata metadata : object) {
type.write(buffer, metadata);
this.type.write(buffer, metadata);
}
this.writeEnd(type, buffer);
this.type.write(buffer, null);
}
protected abstract void writeEnd(final Type<Metadata> type, final ByteBuf buffer) throws Exception;
}
@@ -26,7 +26,7 @@ import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.Type;
public abstract class MetaTypeTemplate extends Type<Metadata> {
public MetaTypeTemplate() {
protected MetaTypeTemplate() {
super("Metadata type", Metadata.class);
}
@@ -24,14 +24,17 @@ package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public abstract class ModernMetaType extends MetaTypeTemplate {
private static final int END = 255;
@Override
public Metadata read(final ByteBuf buffer) throws Exception {
final short index = buffer.readUnsignedByte();
if (index == 0xff) return null; // End of metadata
final MetaType type = this.getType(buffer.readByte());
if (index == END) return null; // End of metadata
final MetaType type = this.getType(Type.VAR_INT.readPrimitive(buffer));
return new Metadata(index, type, type.type().read(buffer));
}
@@ -40,11 +43,11 @@ public abstract class ModernMetaType extends MetaTypeTemplate {
@Override
public void write(final ByteBuf buffer, final Metadata object) throws Exception {
if (object == null) {
buffer.writeByte(0xff);
buffer.writeByte(END);
} else {
buffer.writeByte(object.id());
final MetaType type = object.metaType();
buffer.writeByte(type.typeId());
Type.VAR_INT.writePrimitive(buffer, type.typeId());
type.type().write(buffer, object.getValue());
}
}
@@ -0,0 +1,52 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import io.netty.buffer.ByteBuf;
public abstract class OldMetaType extends MetaTypeTemplate {
private static final int END = 127;
@Override
public Metadata read(final ByteBuf buffer) throws Exception {
final byte index = buffer.readByte();
if (index == END) return null; // End of metadata
final MetaType type = this.getType((index & 224) >> 5);
return new Metadata(index & 31, type, type.type().read(buffer));
}
protected abstract MetaType getType(final int index);
@Override
public void write(final ByteBuf buffer, final Metadata object) throws Exception {
if (object == null) {
buffer.writeByte(END);
} else {
final int index = (object.metaType().typeId() << 5 | object.id() & 31) & 255;
buffer.writeByte(index);
object.metaType().type().write(buffer, object.getValue());
}
}
}
@@ -23,45 +23,14 @@
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import io.netty.buffer.ByteBuf;
public class Particle1_13Type extends Type<Particle> {
@Deprecated/*(forRemoval = true)*/
public class Particle1_13Type extends AbstractParticleType {
public Particle1_13Type() {
super("Particle", Particle.class);
}
@Override
public void write(ByteBuf buffer, Particle object) throws Exception {
Type.VAR_INT.writePrimitive(buffer, object.getId());
for (Particle.ParticleData data : object.getArguments())
data.getType().write(buffer, data.getValue());
}
@Override
public Particle read(ByteBuf buffer) throws Exception {
int type = Type.VAR_INT.readPrimitive(buffer);
Particle particle = new Particle(type);
switch (type) {
// Block / Falling Dust /
case 3:
case 20:
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buffer))); // Flat Block
break;
// Dust
case 11:
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer))); // Red 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer))); // Green 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer))); // Blue 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer)));// Scale 0.01 - 4
break;
// Item
case 27:
particle.getArguments().add(new Particle.ParticleData(Type.FLAT_ITEM, Type.FLAT_ITEM.read(buffer))); // Flat item
break;
}
return particle;
readers.put(3, blockHandler());
readers.put(20, blockHandler());
readers.put(11, dustHandler());
readers.put(27, itemHandler(Type.FLAT_ITEM));
}
}
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import io.netty.buffer.ByteBuf;
@Deprecated/*(forRemoval = true)*/
public class Particle1_13_2Type extends Type<Particle> {
public Particle1_13_2Type() {
@@ -23,46 +23,14 @@
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import io.netty.buffer.ByteBuf;
public class Particle1_14Type extends Type<Particle> {
@Deprecated/*(forRemoval = true)*/
public class Particle1_14Type extends AbstractParticleType {
public Particle1_14Type() {
super("Particle", Particle.class);
}
@Override
public void write(ByteBuf buffer, Particle object) throws Exception {
Type.VAR_INT.writePrimitive(buffer, object.getId());
for (Particle.ParticleData data : object.getArguments())
data.getType().write(buffer, data.getValue());
}
@Override
public Particle read(ByteBuf buffer) throws Exception {
int type = Type.VAR_INT.readPrimitive(buffer);
Particle particle = new Particle(type);
switch (type) {
// Block / Falling Dust /
case 3:
case 23:
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buffer))); // Flat Block
break;
// Dust
case 14:
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer))); // Red 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer))); // Green 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer))); // Blue 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer)));// Scale 0.01 - 4
break;
// Item
case 32:
particle.getArguments().add(new Particle.ParticleData(Type.FLAT_VAR_INT_ITEM, Type.FLAT_VAR_INT_ITEM.read(buffer))); // Flat item
break;
}
return particle;
readers.put(3, blockHandler());
readers.put(23, blockHandler());
readers.put(14, dustHandler());
readers.put(32, itemHandler(Type.FLAT_VAR_INT_ITEM));
}
}
@@ -22,14 +22,15 @@
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.minecraft.metadata.Metadata;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public abstract class ModernMetaListType extends AbstractMetaListType {
@Deprecated/*(forRemoval = true)*/
public class Particle1_16Type extends AbstractParticleType {
@Override
protected void writeEnd(final Type<Metadata> type, final ByteBuf buffer) throws Exception {
type.write(buffer, null);
public Particle1_16Type() {
readers.put(3, blockHandler());
readers.put(23, blockHandler());
readers.put(14, dustHandler());
readers.put(34, itemHandler(Type.FLAT_VAR_INT_ITEM));
}
}
@@ -22,64 +22,18 @@
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import io.netty.buffer.ByteBuf;
public class Particle1_17Type extends Type<Particle> {
@Deprecated/*(forRemoval = true)*/
public class Particle1_17Type extends AbstractParticleType {
public Particle1_17Type() {
super("Particle", Particle.class);
}
@Override
public void write(ByteBuf buffer, Particle object) throws Exception {
Type.VAR_INT.writePrimitive(buffer, object.getId());
for (Particle.ParticleData data : object.getArguments()) {
data.getType().write(buffer, data.getValue());
}
}
@Override
public Particle read(ByteBuf buffer) throws Exception {
int type = Type.VAR_INT.readPrimitive(buffer);
Particle particle = new Particle(type);
switch (type) {
case 3: // Block
case 24: // Falling dust
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buffer))); // Flat Block
break;
case 14: // Dust
case 15: // Dust transition
particle.getArguments().add(new Particle.ParticleData(Type.DOUBLE, Type.DOUBLE.readPrimitive(buffer))); // Red 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.DOUBLE, Type.DOUBLE.readPrimitive(buffer))); // Green 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.DOUBLE, Type.DOUBLE.readPrimitive(buffer))); // Blue 0 - 1
particle.getArguments().add(new Particle.ParticleData(Type.FLOAT, Type.FLOAT.readPrimitive(buffer))); // Scale 0.01 - 4
if (type == 15) {
// Transition to color
particle.getArguments().add(new Particle.ParticleData(Type.DOUBLE, Type.DOUBLE.readPrimitive(buffer))); // Red
particle.getArguments().add(new Particle.ParticleData(Type.DOUBLE, Type.DOUBLE.readPrimitive(buffer))); // Green
particle.getArguments().add(new Particle.ParticleData(Type.DOUBLE, Type.DOUBLE.readPrimitive(buffer))); // Blue
}
break;
case 33: // Item
particle.getArguments().add(new Particle.ParticleData(Type.FLAT_VAR_INT_ITEM, Type.FLAT_VAR_INT_ITEM.read(buffer))); // Flat item
break;
case 36: // Vibration path
particle.getArguments().add(new Particle.ParticleData(Type.POSITION1_14, Type.POSITION1_14.read(buffer))); // From block pos
String resourceLocation = Type.STRING.read(buffer);
if (resourceLocation.equals("block")) {
particle.getArguments().add(new Particle.ParticleData(Type.POSITION1_14, Type.POSITION1_14.read(buffer))); // Target block pos
} else if (resourceLocation.equals("entity")) {
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buffer))); // Target entity
} else {
Via.getPlatform().getLogger().warning("Unknown vibration path position source type: " + resourceLocation);
}
particle.getArguments().add(new Particle.ParticleData(Type.VAR_INT, Type.VAR_INT.readPrimitive(buffer))); // Arrival in ticks
}
return particle;
readers.put(4, blockHandler());
readers.put(25, blockHandler());
readers.put(15, dustHandler());
readers.put(16, dustTransitionHandler());
readers.put(36, itemHandler(Type.FLAT_VAR_INT_ITEM));
readers.put(37, vibrationHandler(Type.POSITION1_14));
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.type.Type;
@Deprecated/*(forRemoval = true)*/
public class Particle1_18Type extends AbstractParticleType {
public Particle1_18Type() {
readers.put(2, blockHandler());
readers.put(3, blockHandler());
readers.put(24, blockHandler());
readers.put(14, dustHandler());
readers.put(15, dustTransitionHandler());
readers.put(35, itemHandler(Type.FLAT_VAR_INT_ITEM));
readers.put(36, vibrationHandler(Type.POSITION1_14));
}
}
@@ -0,0 +1,143 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.minecraft;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.ParticleMappings;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.Particle;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
public class ParticleType extends Type<Particle> {
private final Int2ObjectMap<ParticleReader> readers;
public ParticleType(final Int2ObjectMap<ParticleReader> readers) {
super("Particle", Particle.class);
this.readers = readers;
}
public ParticleType() {
this(new Int2ObjectArrayMap<>());
}
public ParticleTypeFiller filler(final Protocol<?, ?, ?, ?> protocol) {
return this.new ParticleTypeFiller(protocol);
}
@Override
public void write(final ByteBuf buffer, final Particle object) throws Exception {
Type.VAR_INT.writePrimitive(buffer, object.getId());
for (final Particle.ParticleData data : object.getArguments()) {
data.getType().write(buffer, data.getValue());
}
}
@Override
public Particle read(final ByteBuf buffer) throws Exception {
final int type = Type.VAR_INT.readPrimitive(buffer);
final Particle particle = new Particle(type);
final ParticleReader reader = readers.get(type);
if (reader != null) {
reader.read(buffer, particle);
}
return particle;
}
public static ParticleReader itemHandler(final Type<Item> itemType) {
return (buf, particle) -> particle.add(itemType, itemType.read(buf));
}
public static final class Readers {
public static final ParticleReader BLOCK = (buf, particle) -> {
particle.add(Type.VAR_INT, Type.VAR_INT.readPrimitive(buf)); // Flat Block
};
public static final ParticleReader ITEM = itemHandler(Type.FLAT_ITEM);
public static final ParticleReader VAR_INT_ITEM = itemHandler(Type.FLAT_VAR_INT_ITEM);
public static final ParticleReader DUST = (buf, particle) -> {
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Red 0-1
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Green 0-1
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Blue 0-1
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Scale 0.01-4
};
public static final ParticleReader DUST_TRANSITION = (buf, particle) -> {
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Red 0-1
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Green 0-1
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Blue 0-1
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Scale 0.01-4
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Red
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Green
particle.add(Type.FLOAT, Type.FLOAT.readPrimitive(buf)); // Blue
};
public static final ParticleReader VIBRATION = (buf, particle) -> {
particle.add(Type.POSITION1_14, Type.POSITION1_14.read(buf)); // From block pos
final String resourceLocation = Type.STRING.read(buf);
if (resourceLocation.equals("block")) {
particle.add(Type.POSITION1_14, Type.POSITION1_14.read(buf)); // Target block pos
} else if (resourceLocation.equals("entity")) {
particle.add(Type.VAR_INT, Type.VAR_INT.readPrimitive(buf)); // Target entity
} else {
Via.getPlatform().getLogger().warning("Unknown vibration path position source type: " + resourceLocation);
}
particle.add(Type.VAR_INT, Type.VAR_INT.readPrimitive(buf)); // Arrival in ticks
};
}
public final class ParticleTypeFiller {
private final ParticleMappings mappings;
private ParticleTypeFiller(final Protocol<?, ?, ?, ?> protocol) {
this.mappings = protocol.getMappingData().getParticleMappings();
}
public ParticleTypeFiller reader(final String identifier, final ParticleReader reader) {
readers.put(mappings.id(identifier), reader);
return this;
}
public ParticleTypeFiller reader(final int id, final ParticleReader reader) {
readers.put(id, reader);
return this;
}
}
@FunctionalInterface
public interface ParticleReader {
/**
* Reads particle data from the buffer and adds it to the particle data.
*
* @param buf buffer
* @param particle particle
* @throws Exception if an error occurs during buffer reading
*/
void read(ByteBuf buf, Particle particle) throws Exception;
}
}
@@ -44,8 +44,8 @@ public class Position1_14Type extends Type<Position> {
@Override
public void write(ByteBuf buffer, Position object) {
buffer.writeLong((((long) object.getX() & 0x3ffffff) << 38)
| (object.getY() & 0xfff)
| ((((long) object.getZ()) & 0x3ffffff) << 12));
buffer.writeLong((((long) object.x() & 0x3ffffff) << 38)
| (object.y() & 0xfff)
| ((((long) object.z()) & 0x3ffffff) << 12));
}
}
@@ -44,8 +44,8 @@ public class PositionType extends Type<Position> {
@Override
public void write(ByteBuf buffer, Position object) {
buffer.writeLong((((long) object.getX() & 0x3ffffff) << 38)
| ((((long) object.getY()) & 0xfff) << 26)
| (object.getZ() & 0x3ffffff));
buffer.writeLong((((long) object.x() & 0x3ffffff) << 38)
| ((((long) object.y()) & 0xfff) << 26)
| (object.z() & 0x3ffffff));
}
}
@@ -42,8 +42,8 @@ public class VectorType extends Type<Vector> {
@Override
public void write(ByteBuf buffer, Vector object) throws Exception {
Type.INT.write(buffer, object.getBlockX());
Type.INT.write(buffer, object.getBlockY());
Type.INT.write(buffer, object.getBlockZ());
Type.INT.write(buffer, object.blockX());
Type.INT.write(buffer, object.blockY());
Type.INT.write(buffer, object.blockZ());
}
}
@@ -38,8 +38,8 @@ public class VillagerDataType extends Type<VillagerData> {
@Override
public void write(ByteBuf buffer, VillagerData object) throws Exception {
Type.VAR_INT.writePrimitive(buffer, object.getType());
Type.VAR_INT.writePrimitive(buffer, object.getProfession());
Type.VAR_INT.writePrimitive(buffer, object.getLevel());
Type.VAR_INT.writePrimitive(buffer, object.type());
Type.VAR_INT.writePrimitive(buffer, object.profession());
Type.VAR_INT.writePrimitive(buffer, object.level());
}
}
@@ -0,0 +1,53 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntityImpl;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class BlockEntityType1_18 extends Type<BlockEntity> {
public BlockEntityType1_18() {
super(BlockEntity.class);
}
@Override
public BlockEntity read(final ByteBuf buffer) throws Exception {
final byte xz = buffer.readByte();
final short y = buffer.readShort();
final int typeId = Type.VAR_INT.readPrimitive(buffer);
final CompoundTag tag = Type.NBT.read(buffer);
return new BlockEntityImpl(xz, y, typeId, tag);
}
@Override
public void write(final ByteBuf buffer, final BlockEntity entity) throws Exception {
buffer.writeByte(entity.packedXZ());
buffer.writeShort(entity.y());
Type.VAR_INT.writePrimitive(buffer, entity.typeId());
Type.NBT.write(buffer, entity.tag());
}
}
@@ -0,0 +1,57 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2021 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public final class ChunkSectionType1_18 extends Type<ChunkSection> {
private final PaletteType1_18 blockPaletteType;
private final PaletteType1_18 biomePaletteType;
public ChunkSectionType1_18(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super("Chunk Section Type", ChunkSection.class);
this.blockPaletteType = new PaletteType1_18(PaletteType.BLOCKS, globalPaletteBlockBits);
this.biomePaletteType = new PaletteType1_18(PaletteType.BIOMES, globalPaletteBiomeBits);
}
@Override
public ChunkSection read(final ByteBuf buffer) throws Exception {
final ChunkSection chunkSection = new ChunkSectionImpl();
chunkSection.setNonAirBlocksCount(buffer.readShort());
chunkSection.addPalette(PaletteType.BLOCKS, blockPaletteType.read(buffer));
chunkSection.addPalette(PaletteType.BIOMES, biomePaletteType.read(buffer));
return chunkSection;
}
@Override
public void write(final ByteBuf buffer, final ChunkSection section) throws Exception {
buffer.writeShort(section.getNonAirBlocksCount());
blockPaletteType.write(buffer, section.palette(PaletteType.BLOCKS));
biomePaletteType.write(buffer, section.palette(PaletteType.BIOMES));
}
}
@@ -55,6 +55,15 @@ public class ChunkSectionType1_8 extends Type<ChunkSection> {
@Override
public void write(ByteBuf buffer, ChunkSection chunkSection) throws Exception {
throw new UnsupportedOperationException();
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int block = chunkSection.getFlatBlock(x, y, z);
buffer.writeByte(block);
buffer.writeByte(block >> 8);
}
}
}
}
}
@@ -23,12 +23,12 @@
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_13;
import com.viaversion.viaversion.api.type.types.minecraft.ModernMetaType;
@Deprecated/*(forRemoval = true)*/
public class Metadata1_13Type extends ModernMetaType {
@Override
protected MetaType getType(final int index) {
return MetaType1_13.byId(index);
return Types1_13.META_TYPES.byId(index);
}
}
@@ -23,12 +23,12 @@
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.metadata.MetaType;
import com.viaversion.viaversion.api.minecraft.metadata.types.MetaType1_13_2;
import com.viaversion.viaversion.api.type.types.minecraft.ModernMetaType;
@Deprecated/*(forRemoval = true)*/
public class Metadata1_13_2Type extends ModernMetaType {
@Override
protected MetaType getType(final int index) {
return MetaType1_13_2.byId(index);
return Types1_13_2.META_TYPES.byId(index);
}
}
Loaded 100 of 288 files, more files were not shown because too many files have changed in this diff. Show more