Compare commits

..
89 Commits
Author SHA1 Message Date
Nassim Jahnke a6c35c6519 5.8.1 Release 2026-03-30 20:28:09 +02:00
Nassim Jahnke 8b115c7fde Fix attack_range and provides_banner_pattern hashing 2026-03-30 20:22:40 +02:00
Florian Reuth e2d3874f6d Add debug command usage help (#4874) 2026-03-30 15:25:21 +02:00
Florian Reuth 26d8190b23 Send empty tags packet in 1.21.11->26.1 (#4871) 2026-03-29 21:37:32 +02:00
RK_01 d508b6cec1 Add missing fluid block states for kelp, seagrass, and bubble columns (#4870)
Fixes water physics in 26.1
2026-03-29 17:36:08 +02:00
Nassim Jahnke 916ef8c5ac Fix removal of recipe displays 2026-03-29 15:07:44 +02:00
Nassim Jahnke 6b74116ff1 Handle item changes in dialog packets 2026-03-28 17:09:25 +01:00
Nassim Jahnke 5ead6805b9 Distinguish items of different ids for hashing 2026-03-28 11:25:22 +01:00
Nassim Jahnke a6eedfdf0b Bump version to 5.8.1-SNAPSHOT 2026-03-28 11:18:20 +01:00
Nassim Jahnke 38ecd65ee8 5.8.0 Release 2026-03-27 16:12:18 +01:00
Nassim Jahnke 788c1d1b1f Set hashed item amount from click packet
Preserves the amount the player actually had/saw at the end
2026-03-26 20:44:52 +01:00
Nassim Jahnke 0519184da2 Replace 0 count in item hovers 2026-03-25 16:21:55 +01:00
Florian Reuth fd13912295 Fix EntityDataTypes1_21_11#villagerDataType typo 2026-03-25 16:21:23 +01:00
Nassim Jahnke 8d3c36de06 Send empty tags packet if not sent early enough when leaving config stage
Some tags are required before the client finalizes its registries, this lets Via fill them up early enough in later protocols
2026-03-25 16:21:09 +01:00
Nassim Jahnke 219d374d7c Fix item particle type 2026-03-25 16:21:09 +01:00
Nassim Jahnke 9b163e70c3 Remove snapshot bit 2026-03-25 16:21:09 +01:00
Nassim Jahnke 9ed00904f9 26.1-rc-3 2026-03-25 16:21:09 +01:00
Nassim Jahnke e56abf5cac Update identifier files 2026-03-25 16:21:09 +01:00
Florian Reuth 1bf7274dc8 Add empty damage type & banner pattern tags
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-03-25 16:21:09 +01:00
Nassim Jahnke d218451418 26.1-rc-2 2026-03-25 16:21:08 +01:00
Nassim Jahnke 7d8dcce307 Fix pausing daylight cycle 2026-03-25 16:21:08 +01:00
Nassim Jahnke 2f5d527a38 Fix blocks attacks conversion and banner pattern hashing 2026-03-25 16:21:08 +01:00
Nassim Jahnke a16c5a9fc5 26.1-rc-1 2026-03-25 16:21:08 +01:00
Nassim Jahnke 318608b9cd Auto remove new registries from tags too 2026-03-25 16:21:08 +01:00
Nassim Jahnke ae7496fbad 26.1-pre-3 2026-03-25 16:21:07 +01:00
Nassim Jahnke 32a1dfe74f 26.1-pre-2 2026-03-25 16:21:07 +01:00
Nassim Jahnke 815ec24af1 Remove removed registries from command arguments 2026-03-25 16:21:07 +01:00
Nassim Jahnke 8ee0b66eed Always send interact_at 2026-03-25 16:21:07 +01:00
Nassim Jahnke ab2385b975 26.1-pre1 2026-03-25 16:21:07 +01:00
Nassim Jahnke 5a9ccf7c17 Update villager entity data id 2026-03-25 16:21:07 +01:00
Nassim Jahnke 22877d06a7 Replace remaining either holders 2026-03-25 16:21:06 +01:00
Nassim Jahnke 35d85d08a7 Update sound variants 2026-03-25 16:21:06 +01:00
Nassim Jahnke f5bb1c42db 26.1-snapshot-11 2026-03-25 16:21:06 +01:00
Nassim Jahnke cfb8519ae2 26.1-snapshot-10 2026-03-25 16:21:06 +01:00
Nassim Jahnke 4d1fa925ff Add new ambient light colors 2026-03-25 16:21:06 +01:00
Nassim Jahnke fa410b704a Fix cat variant asset change 2026-03-25 16:21:06 +01:00
Nassim Jahnke 483628f1f2 26.1-snapshot-9 2026-03-25 16:21:05 +01:00
Nassim Jahnke 7930e66676 26.1-snapshot-8 (maybe) 2026-03-25 16:21:05 +01:00
Nassim Jahnke 5b547a303a 26.1-snapshot-7 2026-03-25 16:21:05 +01:00
Nassim Jahnke 497d8e17da 26.1-snapshot-6 2026-03-25 16:21:05 +01:00
Nassim Jahnke efbd5d23cd 26.1-snapshot-5 2026-03-25 16:21:05 +01:00
Nassim Jahnke 592b8c8d47 26.1-snapshot-4 2026-03-25 16:21:04 +01:00
Nassim Jahnke 5393edc35b Handle null template items, fix asset id change 2026-03-25 16:21:04 +01:00
Nassim Jahnke 97aff00ced Fill registries used by delayed item loading 2026-03-25 16:21:04 +01:00
Nassim Jahnke 69121c5722 26.1-snapshot-3 2026-03-25 16:21:04 +01:00
Nassim Jahnke ba57197552 26.1-snapshot-2 2026-03-25 16:21:04 +01:00
Nassim Jahnke 7ca372dca4 Update template protocol 2026-03-25 16:21:04 +01:00
Nassim Jahnke e9fb10b63c 26.1-snapshot-1 2026-03-25 16:21:03 +01:00
Florian Reuth ca7696ce12 Allow platforms to append data to connection details protocols (#4859) 2026-03-24 23:17:48 +01:00
Florian Reuth e63c806d64 Fix custom potion effects translation in 1.20.3->1.20.5 (#4858) 2026-03-22 08:34:30 +01:00
Florian Reuth e470ca0002 [ci skip] Update README (#4856) 2026-03-21 19:07:32 +01:00
Florian Reuth 80e90a4401 Fix flower pot block storage 1.12.2->1.13 memory leak (#4852) 2026-03-18 15:05:30 +01:00
Florian Reuth 1d35f2ec35 Produce inlined string in 1.8->1.9 sign update (#4851) 2026-03-16 19:17:21 +01:00
Nassim Jahnke e639eb763a Update ViaNBT 2026-03-13 20:51:32 +01:00
Nassim Jahnke d8343d278d Use var int type in holder set type 2026-03-12 15:12:09 +01:00
Nassim Jahnke 833f49fff3 Swap end and overworld background tracks 2026-03-02 17:33:52 +01:00
Nassim Jahnke cd45a6e7ce 5.7.2 Release 2026-03-01 16:28:28 +01:00
Nassim Jahnke 271362da78 Update dependencies 2026-03-01 16:28:16 +01:00
Nassim Jahnke 05562c27c1 Fix nether biome sky colors, add missing dimension ambient sounds 2026-02-22 13:47:24 +01:00
Nassim Jahnke 5b4ed02748 Handle number format in set_score packet 2026-02-21 16:03:13 +01:00
Nassim Jahnke fe4e407520 Add gradle to dependabot config 2026-02-20 22:17:25 +01:00
Nassim Jahnke f003b6b84a Only do compression handler reorder on old servers after compression is enabled 2026-02-20 21:58:25 +01:00
Nassim Jahnke 207e085120 Add breath_of_the_nautilus to mob effects enum type 2026-02-20 19:18:19 +01:00
Nassim Jahnke 0a155651a1 Handle 1.21.9->1.21.11 biome sounds and particles 2026-02-20 13:56:19 +01:00
Florian Reuth d061083a8a Handle nested lore components in item_hover handling again (#4830) 2026-02-12 21:31:33 +01:00
Nassim Jahnke ad4c8e42f2 Add system property to disable legacy compression reorder 2026-02-09 17:56:19 +01:00
Florian Reuth b8b13f5831 [ci skip] Update my donation URL (#4826) 2026-02-05 17:09:38 +01:00
FlorianMichael 4dc533506f Don't register a cooldown rewriter in 1.17->1.17.1 (#4824) 2026-02-02 16:16:20 +01:00
dependabot[bot] a166b70996 [ci skip] Bump actions/checkout from 6.0.1 to 6.0.2 (#4822)
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/8e8c483db84b4bee98b60c0593521ed34d9990e8...de0fac2e4500dabe0009e67214ff5f5447ce83dd)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 14:07:37 +01:00
dependabot[bot] 639e8c454d [ci skip] Bump actions/setup-java from 5.1.0 to 5.2.0 (#4823)
Bumps [actions/setup-java](https://github.com/actions/setup-java) from 5.1.0 to 5.2.0.
- [Release notes](https://github.com/actions/setup-java/releases)
- [Commits](https://github.com/actions/setup-java/compare/f2beeb24e141e01a676f977032f5a29d81c9e27e...be666c2fcd27ec809703dec50e508c2fdc7f6654)

---
updated-dependencies:
- dependency-name: actions/setup-java
  dependency-version: 5.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-02 14:07:23 +01:00
FlorianMichael 61fc96ee11 Allow platforms to change compression names (#4821) 2026-01-31 21:08:01 +01:00
Nassim Jahnke 56259c8318 Update supported Velocity versions 2026-01-31 12:02:24 +01:00
FlorianMichael a8637d9a06 Fix play state compression when already set during login in 1.8->1.9 (#4820) 2026-01-30 22:02:40 +01:00
FlorianMichael ce607b5cc7 Use compression handler names instead for utility method (#4818) 2026-01-30 21:28:37 +01:00
FlorianMichael aa9a615c6b [ci skip] Small code cleanups (#4819) 2026-01-30 21:25:40 +01:00
FlorianMichael 8febef07c3 Add ViaChannelInitializer#reorderPipeline (#4817) 2026-01-29 17:09:42 +01:00
Nassim Jahnke 13fcce6059 Use right method for sub 1.21.5 item_name/custom_name item_hover handling 2026-01-28 17:12:34 +01:00
FlorianMichael cf6427325c Call component rewriter for component item components (#4812) 2026-01-28 12:10:47 +01:00
ValapheeandFlorianMichael 2c30a2748c Display out of bounds enchantments in item lore in 1.17->1.17.1 (#4743)
Co-authored-by: FlorianMichael <git@florianmichael.de>
2026-01-25 20:29:38 +01:00
Nassim Jahnke 1ca5b33304 Fix trusted tag limiting 2026-01-25 13:13:55 +01:00
Nassim Jahnke 265859bdae Re-use byte array in hash builder 2026-01-25 10:59:39 +01:00
FlorianMichael 93e29ac832 Use BlockRewriter1_21_5 in 1.21.7->1.21.9 & 1.21.9->1.21.11 (#4807) 2026-01-24 19:35:27 +01:00
FlorianMichael 4735795323 [ci skip] Remove Gradle wrapper update action (#4805) 2026-01-24 19:25:39 +01:00
FlorianMichael fe5732b616 Make Config#originalRootSection consistent (#4798) 2026-01-21 17:18:27 +01:00
RK_01 b0d9b747de Add ProtocolVersionRange#getMin and ProtocolVersionRange#getMax (#4797) 2026-01-19 21:08:30 +01:00
Nassim Jahnke 3f0f973fac Use synchronized map for config to preserve correct order on late saves 2026-01-19 19:33:00 +01:00
RK_01 1fa3f15d91 Handle 1.21->1.21.2 empty food component split fully (#4796) 2026-01-18 21:39:40 +01:00
FlorianMichael 2979b9d63d Also send version type; always send player details (#4795) 2026-01-18 21:00:52 +01:00
FlorianMichael a734a4a9d1 Make UserConnectionViaVersionPlatform a proxy platform by default (#4794) 2026-01-18 21:00:25 +01:00
162 changed files with 3111 additions and 575 deletions

No files matched your search

+1 -1
View File
@@ -1,3 +1,3 @@
github: kennytv
patreon: kennytv
custom: ['https://florianmichael.de/donate']
custom: ['https://florianreuth.de/donate']
+6
View File
@@ -6,3 +6,9 @@ updates:
directory: "/"
schedule:
interval: "monthly"
- package-ecosystem: "gradle"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
+3 -3
View File
@@ -11,13 +11,13 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # 5.0.0
uses: gradle/actions/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # 5.0.1
- name: Set up JDK 17
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # 5.1.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
with:
distribution: 'temurin'
java-version: 17
+3 -3
View File
@@ -16,13 +16,13 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@4d9f0ba0025fe599b4ebab900eb7f3a1d93ef4c2 # 5.0.0
uses: gradle/actions/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # 5.0.1
- name: Set up JDK 17
uses: actions/setup-java@f2beeb24e141e01a676f977032f5a29d81c9e27e # 5.1.0
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
with:
distribution: 'temurin'
java-version: 17
@@ -1,22 +0,0 @@
name: Update Gradle Wrapper
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 0"
permissions:
contents: write
pull-requests: write
jobs:
update-gradle-wrapper:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # 6.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Update Gradle Wrapper
uses: gradle-update/update-gradle-wrapper-action@512b1875f3b6270828abfe77b247d5895a2da1e5 # 2.1.0
+20 -9
View File
@@ -7,11 +7,15 @@
**Allows the connection of higher client versions to lower server versions -
it works on any platform you can think of.**
The base ViaVersion jar runs on Paper and Velocity. We also have projects integrating ViaVersion to run
on Fabric, Forge, Sponge, or as a standalone proxy to join from basically any client version on
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\* projects.**
The base ViaVersion jar runs on [Paper](https://papermc.io/software/paper/)
and [Velocity](https://papermc.io/software/velocity/). We also have projects integrating ViaVersion to run
on [Fabric](https://github.com/ViaVersion/ViaFabric), [Forge](https://github.com/ViaVersion/ViaForge), [Bungee](https://github.com/ViaVersion/ViaBungee), [Sponge](https://github.com/ViaVersion/ViaSponge),
or as [a standalone proxy](https://github.com/ViaVersion/ViaProxy) to join from basically any client version on
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\*
projects.**
Note that ViaVersion will be able to **run best on either Paper servers or through [ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus?tab=readme-ov-file#viafabricplus)** due to having
Note that ViaVersion will be able to **run best on either Paper servers or
through [ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus?tab=readme-ov-file#viafabricplus)** due to having
direct access to client/server state and more extensive API.
Supported Versions:
@@ -22,10 +26,16 @@ Supported Versions:
Snapshot support
--------
**ViaVersion will only be released a few days *after* a Minecraft update** unless the protocol changes of the update were trivial. If you want early-access, usually days or even weeks before the final release, you can subscribe to either:
- [GitHub Sponsors](https://github.com/sponsors/kennytv/sponsorships?sponsor=kennytv&tier_id=385613&preview=false) (preferred option. Use the `/verify` command on this Discord after), or alternatively
- [Patreon](https://www.patreon.com/kennytv/membership) (see the highest tier and make sure to link Patreon to your Discord account under Settings->Connections)
This also includes access to a private repository with the code, which will be pushed to the public repository after the given delay on a Minecraft update.
**ViaVersion will only be released a few days *after* a Minecraft update** unless the protocol changes of the update
were trivial. If you want early-access, usually days or even weeks before the final release, you can subscribe to
either:
- [GitHub Sponsors](https://github.com/sponsors/kennytv/sponsorships?sponsor=kennytv&tier_id=385613&preview=false) (
preferred option. Use the `/verify` command on this Discord after), or alternatively
- [Patreon](https://www.patreon.com/kennytv/membership) (see the highest tier and make sure to link Patreon to your
Discord account under Settings->Connections)
This also includes access to a private repository with the code, which will be pushed to the public repository after
the given delay on a Minecraft update.
Releases/Dev Builds
--------
@@ -89,7 +99,8 @@ You need JDK 17 or newer to build ViaVersion.
Mapping Files
--------------
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings). The generated mapping output is stored [here](./common/src/main/resources/assets/viaversion).
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings). The
generated mapping output is stored [here](./common/src/main/resources/assets/viaversion).
Resources
--------
@@ -134,6 +134,15 @@ public interface ProtocolInfo {
void setUuid(UUID uuid);
/**
* Returns whether compression is enabled for this connection.
*
* @return whether compression is enabled
*/
boolean compressionEnabled();
void setCompressionEnabled(boolean compressionEnabled);
/**
* Returns the user's pipeline.
*
@@ -170,6 +170,8 @@ public interface MappingData {
@Nullable FullMappings getRecipeSerializerMappings();
@Nullable FullMappings getSlotDisplayMappings();
@Nullable FullMappings getDataComponentSerializerMappings();
default @Nullable FullMappings getFullMappings(final MappingType mappingType) {
@@ -45,6 +45,7 @@ public class MappingDataBase implements MappingData {
protected FullMappings entityMappings;
protected FullMappings recipeSerializerMappings;
protected FullMappings itemDataSerializerMappings;
protected FullMappings slotDisplayMappings;
protected FullMappings attributeMappings;
protected FullMappings blockEntityMappings;
protected ParticleMappings particleMappings;
@@ -89,6 +90,7 @@ public class MappingDataBase implements MappingData {
entityMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "entities");
argumentTypeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "argumenttypes");
slotDisplayMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "slot_displays");
recipeSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "recipe_serializers");
itemDataSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "data_component_type");
attributeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "attributes");
@@ -335,6 +337,11 @@ public class MappingDataBase implements MappingData {
return recipeSerializerMappings;
}
@Override
public @Nullable FullMappings getSlotDisplayMappings() {
return slotDisplayMappings;
}
@Override
public @Nullable IntSet changedBlocks() {
return changedBlocks;
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
@@ -40,6 +41,7 @@ public interface HolderSet {
* @return a new holder set
*/
static HolderSet of(final String tagKey) {
Preconditions.checkNotNull(tagKey);
return new HolderSetImpl.Tag(tagKey);
}
@@ -50,6 +52,7 @@ public interface HolderSet {
* @return a new holder set
*/
static HolderSet of(final int[] ids) {
Preconditions.checkNotNull(ids);
return new HolderSetImpl.Ids(ids);
}
@@ -58,8 +58,8 @@ public record PaintingVariant(int width, int height, String assetId, @Nullable T
final int width = Types.VAR_INT.readPrimitive(buffer);
final int height = Types.VAR_INT.readPrimitive(buffer);
final String assetId = Types.STRING.read(buffer);
final Tag title = Types.OPTIONAL_TAG.read(buffer);
final Tag author = Types.OPTIONAL_TAG.read(buffer);
final Tag title = Types.TRUSTED_OPTIONAL_TAG.read(buffer);
final Tag author = Types.TRUSTED_OPTIONAL_TAG.read(buffer);
return new PaintingVariant(width, height, assetId, title, author);
}
@@ -68,8 +68,8 @@ public record PaintingVariant(int width, int height, String assetId, @Nullable T
Types.VAR_INT.writePrimitive(buffer, variant.width());
Types.VAR_INT.writePrimitive(buffer, variant.height());
Types.STRING.write(buffer, variant.assetId());
Types.OPTIONAL_TAG.write(buffer, variant.title());
Types.OPTIONAL_TAG.write(buffer, variant.author());
Types.TRUSTED_OPTIONAL_TAG.write(buffer, variant.title());
Types.TRUSTED_OPTIONAL_TAG.write(buffer, variant.author());
}
@Override
@@ -79,8 +79,8 @@ public record PaintingVariant(int width, int height, String assetId, @Nullable T
.write("width", Types.INT, value.width())
.write("height", Types.INT, value.height())
.write("asset_id", Types.IDENTIFIER, Key.of(value.assetId()))
.writeOptional("title", Types.TAG, value.title())
.writeOptional("author", Types.TAG, value.author()));
.writeOptional("title", Types.TRUSTED_TAG, value.title())
.writeOptional("author", Types.TRUSTED_TAG, value.author()));
}
@Override
@@ -34,7 +34,9 @@ public enum RegistryType implements RegistryKey {
FLUID("fluid"),
ENTITY("entity_type"),
GAME_EVENT("game_event"),
ENCHANTMENT("enchantment");
ENCHANTMENT("enchantment"),
DAMAGE_TYPE("damage_type"),
BANNER_PATTERN("banner_pattern");
private static final Map<String, RegistryType> MAP = new HashMap<>();
private static final RegistryType[] VALUES = values();
@@ -61,6 +61,17 @@ public interface ChunkSection {
void setNonAirBlocksCount(int nonAirBlocksCount);
/**
* Returns the number of fluid blocks in this section.
* <p>
* Available with versions 26.1+.
*
* @return fluid blocks in this section
*/
int getFluidCount();
void setFluidCount(int fluidCount);
/**
* Returns whether this section holds light data.
* Only true for &lt; 1.14 chunks.
@@ -30,6 +30,7 @@ public class ChunkSectionImpl implements ChunkSection {
private final EnumMap<PaletteType, DataPalette> palettes = new EnumMap<>(PaletteType.class);
private ChunkSectionLight light;
private int nonAirBlocksCount;
private int fluidCount;
public ChunkSectionImpl() {
}
@@ -58,6 +59,16 @@ public class ChunkSectionImpl implements ChunkSection {
this.nonAirBlocksCount = nonAirBlocksCount;
}
@Override
public int getFluidCount() {
return fluidCount;
}
@Override
public void setFluidCount(final int fluidCount) {
this.fluidCount = fluidCount;
}
@Override
public @Nullable ChunkSectionLight getLight() {
return light;
@@ -160,6 +160,10 @@ public final class StructuredDataContainer implements Copyable {
}
public <T, V> void replace(final StructuredDataKey<T> key, final StructuredDataKey<V> toKey, final Function<T, @Nullable V> valueMapper) {
replace(key, toKey, valueMapper, null);
}
public <T, V> void replace(final StructuredDataKey<T> key, final StructuredDataKey<V> toKey, final Function<T, @Nullable V> valueMapper, final Runnable emptyValueHandler) {
final StructuredData<?> data = this.data.remove(key);
if (data == null) {
return;
@@ -175,6 +179,9 @@ public final class StructuredDataContainer implements Copyable {
} else {
// Also replace the key for empty data
setEmpty(toKey);
if (emptyValueHandler != null) {
emptyValueHandler.run();
}
}
}
@@ -37,6 +37,7 @@ import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_5;
import com.viaversion.viaversion.api.minecraft.item.data.AdventureModePredicate;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrim;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.AttackRange;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
@@ -47,7 +48,8 @@ import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
import com.viaversion.viaversion.api.minecraft.item.data.BlocksAttacks;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant26_1;
import com.viaversion.viaversion.api.minecraft.item.data.DamageType;
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
import com.viaversion.viaversion.api.minecraft.item.data.DebugStickState;
@@ -65,12 +67,14 @@ import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.ItemModel;
import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable.JukeboxSong;
import com.viaversion.viaversion.api.minecraft.item.data.KineticWeapon;
import com.viaversion.viaversion.api.minecraft.item.data.LockCode;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.PiercingWeapon;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesBannerPatterns;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.Repairable;
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
@@ -98,8 +102,8 @@ import com.viaversion.viaversion.util.Unit;
* Holds data component keys.
*
* @param identifier string identifier
* @param type data type
* @param <T> data type
* @param type data type
* @param <T> data type
* @see VersionedTypes
*/
public record StructuredDataKey<T>(String identifier, Type<T> type) {
@@ -113,7 +117,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Unit> UNBREAKABLE1_21_5 = new StructuredDataKey<>("unbreakable", Types.EMPTY);
public static final StructuredDataKey<Tag> CUSTOM_NAME = new StructuredDataKey<>("custom_name", Types.TEXT_COMPONENT_TAG);
public static final StructuredDataKey<Float> MINIMUM_ATTACK_CHARGE = new StructuredDataKey<>("minimum_attack_charge", Types.FLOAT);
public static final StructuredDataKey<DamageType> DAMAGE_TYPE = new StructuredDataKey<>("damage_type", DamageType.TYPE);
public static final StructuredDataKey<DamageType> DAMAGE_TYPE1_21_11 = new StructuredDataKey<>("damage_type", DamageType.TYPE1_21_11);
public static final StructuredDataKey<Integer> DAMAGE_TYPE26_1 = new StructuredDataKey<>("damage_type", new SynchronizedRegistryValueType(RegistryKey.of("damage_type")));
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TEXT_COMPONENT_TAG);
public static final StructuredDataKey<ItemModel> ITEM_MODEL = new StructuredDataKey<>("item_model", ItemModel.TYPE);
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", new ArrayType<>(Types.TEXT_COMPONENT_TAG, 256));
@@ -142,7 +147,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
public static final StructuredDataKey<UseCooldown> USE_COOLDOWN = new StructuredDataKey<>("use_cooldown", UseCooldown.TYPE);
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
public static final StructuredDataKey<DamageResistant> DAMAGE_RESISTANT = new StructuredDataKey<>("damage_resistant", DamageResistant.TYPE);
public static final StructuredDataKey<DamageResistant1_21_2> DAMAGE_RESISTANT1_21_2 = new StructuredDataKey<>("damage_resistant", DamageResistant1_21_2.TYPE);
public static final StructuredDataKey<DamageResistant26_1> DAMAGE_RESISTANT26_1 = new StructuredDataKey<>("damage_resistant", DamageResistant26_1.TYPE);
public static final StructuredDataKey<ToolProperties> TOOL1_20_5 = new StructuredDataKey<>("tool", ToolProperties.TYPE1_20_5);
public static final StructuredDataKey<ToolProperties> TOOL1_21_5 = new StructuredDataKey<>("tool", ToolProperties.TYPE1_21_5);
public static final StructuredDataKey<Weapon> WEAPON = new StructuredDataKey<>("weapon", Weapon.TYPE);
@@ -155,12 +161,15 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
public static final StructuredDataKey<Key> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.IDENTIFIER);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS1_21_5 = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE1_21_5);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS26_1 = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE26_1);
public static final StructuredDataKey<PiercingWeapon> PIERCING_WEAPON = new StructuredDataKey<>("piercing_weapon", PiercingWeapon.TYPE);
public static final StructuredDataKey<KineticWeapon> KINETIC_WEAPON = new StructuredDataKey<>("kinetic_weapon", KineticWeapon.TYPE);
public static final StructuredDataKey<SwingAnimation> SWING_ANIMATION = new StructuredDataKey<>("swing_animation", SwingAnimation.TYPE);
public static final StructuredDataKey<Integer> ADDITIONAL_TRADE_COST = new StructuredDataKey<>("additional_trade_cost", Types.VAR_INT);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS1_20_5 = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE1_20_5);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS1_21_5 = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE1_21_5);
public static final StructuredDataKey<Integer> DYE = new StructuredDataKey<>("dye", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<DyedColor> DYED_COLOR1_20_5 = new StructuredDataKey<>("dyed_color", DyedColor.TYPE1_20_5);
public static final StructuredDataKey<DyedColor> DYED_COLOR1_21_5 = new StructuredDataKey<>("dyed_color", DyedColor.TYPE1_21_5);
public static final StructuredDataKey<Integer> MAP_COLOR = new StructuredDataKey<>("map_color", Types.INT);
@@ -186,11 +195,15 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Holder<Instrument1_20_5>> INSTRUMENT1_20_5 = new StructuredDataKey<>("instrument", Instrument1_20_5.TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT1_21_2 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
public static final StructuredDataKey<EitherHolder<Instrument1_21_2>> INSTRUMENT1_21_5 = new StructuredDataKey<>("instrument", Instrument1_21_2.EITHER_HOLDER_TYPE);
public static final StructuredDataKey<ProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial.TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT26_1 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
public static final StructuredDataKey<ProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL1_21_5 = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial.TYPE);
public static final StructuredDataKey<Holder<ArmorTrimMaterial>> PROVIDES_TRIM_MATERIAL26_1 = new StructuredDataKey<>("provides_trim_material", ArmorTrimMaterial.TYPE1_21_5);
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21_5 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21_5);
public static final StructuredDataKey<Key> PROVIDES_BANNER_PATTERNS = new StructuredDataKey<>("provides_banner_patterns", Types.TAG_KEY);
public static final StructuredDataKey<Holder<JukeboxSong>> JUKEBOX_PLAYABLE26_1 = new StructuredDataKey<>("jukebox_playable", JukeboxSong.TYPE);
public static final StructuredDataKey<Key> PROVIDES_BANNER_PATTERNS1_21_5 = new StructuredDataKey<>("provides_banner_patterns", Types.TAG_KEY);
public static final StructuredDataKey<ProvidesBannerPatterns> PROVIDES_BANNER_PATTERNS26_1 = new StructuredDataKey<>("provides_banner_patterns", ProvidesBannerPatterns.TYPE);
public static final StructuredDataKey<Tag> RECIPES = new StructuredDataKey<>("recipes", Types.TAG);
public static final StructuredDataKey<LodestoneTracker> LODESTONE_TRACKER = new StructuredDataKey<>("lodestone_tracker", LodestoneTracker.TYPE);
public static final StructuredDataKey<FireworkExplosion> FIREWORK_EXPLOSION = new StructuredDataKey<>("firework_explosion", FireworkExplosion.TYPE);
@@ -223,8 +236,10 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> RABBIT_VARIANT = new StructuredDataKey<>("rabbit/variant", EnumTypes.RABBIT_VARIANT);
public static final StructuredDataKey<Integer> PIG_VARIANT = new StructuredDataKey<>("pig/variant", new SynchronizedRegistryValueType(RegistryKey.of("pig_variant")));
public static final StructuredDataKey<Integer> COW_VARIANT = new StructuredDataKey<>("cow/variant", new SynchronizedRegistryValueType(RegistryKey.of("cow_variant")));
public static final StructuredDataKey<Either<Integer, String>> CHICKEN_VARIANT = new StructuredDataKey<>("chicken/variant", new SynchronizedRegistryEitherType(RegistryKey.of("chicken_variant")));
public static final StructuredDataKey<Either<Integer, String>> ZOMBIE_NAUTILUS_VARIANT = new StructuredDataKey<>("zombie_nautilus/variant", new SynchronizedRegistryEitherType(RegistryKey.of("zombie_nautilus_variant"))); // ???
public static final StructuredDataKey<Either<Integer, String>> CHICKEN_VARIANT1_21_5 = new StructuredDataKey<>("chicken/variant", new SynchronizedRegistryEitherType(RegistryKey.of("chicken_variant")));
public static final StructuredDataKey<Integer> CHICKEN_VARIANT26_1 = new StructuredDataKey<>("chicken/variant", new SynchronizedRegistryValueType(RegistryKey.of("chicken_variant")));
public static final StructuredDataKey<Either<Integer, String>> ZOMBIE_NAUTILUS_VARIANT1_21_11 = new StructuredDataKey<>("zombie_nautilus/variant", new SynchronizedRegistryEitherType(RegistryKey.of("zombie_nautilus_variant"))); // ???
public static final StructuredDataKey<Integer> ZOMBIE_NAUTILUS_VARIANT26_1 = new StructuredDataKey<>("zombie_nautilus/variant", new SynchronizedRegistryValueType(RegistryKey.of("zombie_nautilus_variant")));
public static final StructuredDataKey<Integer> FROG_VARIANT = new StructuredDataKey<>("frog/variant", new SynchronizedRegistryValueType(RegistryKey.of("frog_variant")));
public static final StructuredDataKey<Integer> HORSE_VARIANT = new StructuredDataKey<>("horse/variant", EnumTypes.HORSE_VARIANT);
public static final StructuredDataKey<Holder<PaintingVariant>> PAINTING_VARIANT = new StructuredDataKey<>("painting/variant", PaintingVariant.TYPE1_21_2);
@@ -234,6 +249,10 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> CAT_COLLAR = new StructuredDataKey<>("cat/collar", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> SHEEP_COLOR = new StructuredDataKey<>("sheep/color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> SHULKER_COLOR = new StructuredDataKey<>("shulker/color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> PIG_SOUND_VARIANT = new StructuredDataKey<>("pig/sound_variant", new SynchronizedRegistryValueType(RegistryKey.of("pig_sound_variant")));
public static final StructuredDataKey<Integer> COW_SOUND_VARIANT = new StructuredDataKey<>("cow/sound_variant", new SynchronizedRegistryValueType(RegistryKey.of("cow_sound_variant")));
public static final StructuredDataKey<Integer> CHICKEN_SOUND_VARIANT = new StructuredDataKey<>("chicken/sound_variant", new SynchronizedRegistryValueType(RegistryKey.of("chicken_sound_variant")));
public static final StructuredDataKey<Integer> CAT_SOUND_VARIANT = new StructuredDataKey<>("cat/sound_variant", new SynchronizedRegistryValueType(RegistryKey.of("cat_sound_variant")));
// These are only safe to use after protocol loading
public static final StructuredDataKeys1_20_5 V1_20_5 = VersionedTypes.V1_20_5.structuredDataKeys();
@@ -35,9 +35,9 @@ public class StructuredDataKeys1_21_2 extends VersionedStructuredDataKeys {
public final StructuredDataKey<Item> useRemainder;
public StructuredDataKeys1_21_2(final VersionedTypesHolder types) {
this.container = add("container", new ContainerContentsType(types.item()));
this.chargedProjectiles = add("charged_projectiles", types.itemArray());
this.bundleContents = add("bundle_contents", types.itemArray());
this.useRemainder = add("use_remainder", types.item());
this.container = add("container", new ContainerContentsType(types.optionalItemTemplate()));
this.chargedProjectiles = add("charged_projectiles", types.itemTemplateArray());
this.bundleContents = add("bundle_contents", types.itemTemplateArray());
this.useRemainder = add("use_remainder", types.itemTemplate());
}
}
@@ -33,8 +33,8 @@ public final class EntityDataTypes1_20_3 extends AbstractEntityDataTypes {
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType = add(7, Types.ITEM1_20_2);
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
@@ -33,8 +33,8 @@ public final class EntityDataTypes1_20_5 extends AbstractEntityDataTypes {
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
@@ -35,8 +35,8 @@ public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
@@ -34,8 +34,8 @@ public final class EntityDataTypes1_21_11 extends AbstractEntityDataTypes {
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
@@ -47,7 +47,7 @@ public final class EntityDataTypes1_21_11 extends AbstractEntityDataTypes {
public final EntityDataType optionalBlockStateType = add(15, Types.VAR_INT);
public final EntityDataType particleType;
public final EntityDataType particlesType;
public final EntityDataType villagerDatatType = add(18, Types.VILLAGER_DATA);
public final EntityDataType villagerDataType = add(18, Types.VILLAGER_DATA);
public final EntityDataType optionalVarIntType = add(19, Types.OPTIONAL_VAR_INT);
public final EntityDataType poseType = add(20, Types.VAR_INT);
public final EntityDataType catVariantType = add(21, Types.VAR_INT);
@@ -35,8 +35,8 @@ public final class EntityDataTypes1_21_2 extends AbstractEntityDataTypes {
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
@@ -34,8 +34,8 @@ public final class EntityDataTypes1_21_5 extends AbstractEntityDataTypes {
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
@@ -34,8 +34,8 @@ public final class EntityDataTypes1_21_9 extends AbstractEntityDataTypes {
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
@@ -0,0 +1,82 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes26_1 extends AbstractEntityDataTypes {
public final EntityDataType byteType = add(0, Types.BYTE);
public final EntityDataType varIntType = add(1, Types.VAR_INT);
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
public final EntityDataType blockPositionType = add(10, Types.BLOCK_POSITION1_14);
public final EntityDataType optionalBlockPositionType = add(11, Types.OPTIONAL_POSITION_1_14);
public final EntityDataType directionType = add(12, Types.VAR_INT);
public final EntityDataType optionalUUIDType = add(13, Types.OPTIONAL_UUID);
public final EntityDataType blockStateType = add(14, Types.VAR_INT);
public final EntityDataType optionalBlockStateType = add(15, Types.VAR_INT);
public final EntityDataType particleType;
public final EntityDataType particlesType;
public final EntityDataType villagerDataType = add(18, Types.VILLAGER_DATA);
public final EntityDataType optionalVarIntType = add(19, Types.OPTIONAL_VAR_INT);
public final EntityDataType poseType = add(20, Types.VAR_INT);
public final EntityDataType catVariantType = add(21, Types.VAR_INT);
public final EntityDataType catSoundVariant = add(22, Types.VAR_INT);
public final EntityDataType cowVariantType = add(23, Types.VAR_INT);
public final EntityDataType cowSoundVariant = add(24, Types.VAR_INT);
public final EntityDataType wolfVariantType = add(25, Types.VAR_INT);
public final EntityDataType wolfSoundVariantType = add(26, Types.VAR_INT);
public final EntityDataType frogVariantType = add(27, Types.VAR_INT);
public final EntityDataType pigVariantType = add(28, Types.VAR_INT);
public final EntityDataType pigSoundVariant = add(29, Types.VAR_INT);
public final EntityDataType chickenVariantType = add(30, Types.VAR_INT);
public final EntityDataType chickenSoundVariant = add(31, Types.VAR_INT);
public final EntityDataType zombieNautilusVariantType = add(32, Types.VAR_INT);
public final EntityDataType optionalGlobalPosition = add(33, Types.OPTIONAL_GLOBAL_POSITION);
public final EntityDataType paintingVariantType = add(34, PaintingVariant.TYPE1_21_2);
public final EntityDataType snifferState = add(35, Types.VAR_INT);
public final EntityDataType armadilloState = add(36, Types.VAR_INT);
public final EntityDataType copperGolemState = add(37, Types.VAR_INT);
public final EntityDataType weatheringCopperState = add(38, Types.VAR_INT);
public final EntityDataType vector3FType = add(39, Types.VECTOR3F);
public final EntityDataType quaternionType = add(40, Types.QUATERNION);
public final EntityDataType mannequinProfileType = add(41, Types.RESOLVABLE_PROFILE);
public final EntityDataType humanoidArmType = add(42, Types.VAR_INT);
public EntityDataTypes26_1(final VersionedTypesHolder types) {
super(43);
this.itemType = add(7, types.item());
this.particleType = add(16, types.particle());
this.particlesType = add(17, types.particles());
}
}
@@ -76,4 +76,23 @@ public interface Item extends ItemBase {
*/
@Override
Item copy();
/**
* Returns whether the item is a template item.
*
* @return whether the item is a template item
*/
default boolean isTemplate() {
return false;
}
/**
* Returns whether the item is null or empty.
*
* @param item item
* @return whether the item is null or empty
*/
static boolean isEmpty(@Nullable final Item item) {
return item == null || item.isEmpty();
}
}
@@ -0,0 +1,59 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
public class StructuredItemTemplate extends StructuredItem {
public StructuredItemTemplate(final int identifier, final int amount) {
super(identifier, amount, new StructuredDataContainer());
}
public StructuredItemTemplate(final int identifier, final int amount, final StructuredDataContainer data) {
super(identifier, amount, data);
}
@Override
public void setIdentifier(final int identifier) {
Preconditions.checkArgument(identifier > 0, "Template item cannot be empty");
super.setIdentifier(identifier);
}
@Override
public void setAmount(final int amount) {
Preconditions.checkArgument(amount > 0, "Template item cannot be empty");
super.setAmount(amount);
}
@Override
public boolean isTemplate() {
return true;
}
@Override
public StructuredItemTemplate copy() {
return new StructuredItemTemplate(identifier(), amount(), dataContainer().copy());
}
}
@@ -56,8 +56,8 @@ public record AttackRange(float minRange, float maxRange,
@Override
public void write(final Ops ops, final AttackRange AttackRange) {
ops.writeMap(map -> map
.writeOptional("min_range", Types.FLOAT, AttackRange.minRange, 0F)
.writeOptional("max_range", Types.FLOAT, AttackRange.maxRange, 3F)
.writeOptional("min_reach", Types.FLOAT, AttackRange.minRange, 0F)
.writeOptional("max_reach", Types.FLOAT, AttackRange.maxRange, 3F)
.writeOptional("min_creative_reach", Types.FLOAT, AttackRange.minCreativeRange, 0F)
.writeOptional("max_creative_reach", Types.FLOAT, AttackRange.maxCreativeRange, 5F)
.writeOptional("hitbox_margin", Types.FLOAT, AttackRange.hitboxMargin, 0.3F)
@@ -43,12 +43,12 @@ public record BlocksAttacks(
float disableCooldownScale,
DamageReduction[] damageReductions,
ItemDamageFunction itemDamage,
@Nullable String bypassedByTag,
@Nullable HolderSet bypassedBy, // always a tag before 26.1
@Nullable Holder<SoundEvent> blockSound,
@Nullable Holder<SoundEvent> disableSound
) implements Rewritable {
public static final Type<BlocksAttacks> TYPE = new Type<>(BlocksAttacks.class) {
public static final Type<BlocksAttacks> TYPE1_21_5 = new Type<>(BlocksAttacks.class) {
@Override
public BlocksAttacks read(final ByteBuf buffer) {
@@ -59,7 +59,7 @@ public record BlocksAttacks(
final String bypassedByTag = Types.OPTIONAL_STRING.read(buffer);
final Holder<SoundEvent> blockSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
final Holder<SoundEvent> disableSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
return new BlocksAttacks(blockDelaySeconds, disableCooldownScale, damageReductions, itemDamage, bypassedByTag, blockSound, disableSound);
return new BlocksAttacks(blockDelaySeconds, disableCooldownScale, damageReductions, itemDamage, bypassedByTag != null ? HolderSet.of(bypassedByTag) : null, blockSound, disableSound);
}
@Override
@@ -68,7 +68,7 @@ public record BlocksAttacks(
buffer.writeFloat(value.disableCooldownScale());
DamageReduction.ARRAY_TYPE.write(buffer, value.damageReductions());
ItemDamageFunction.TYPE.write(buffer, value.itemDamage());
Types.OPTIONAL_STRING.write(buffer, value.bypassedByTag());
Types.OPTIONAL_STRING.write(buffer, value.bypassedBy() != null ? value.bypassedBy().tagKey() : null);
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.blockSound());
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.disableSound());
}
@@ -82,7 +82,47 @@ public record BlocksAttacks(
.writeOptional("disable_cooldown_scale", Types.FLOAT, value.disableCooldownScale(), 1F)
.writeOptional("damage_reductions", DamageReduction.ARRAY_TYPE, value.damageReductions(), defaultDamageReductions)
.writeOptional("item_damage", ItemDamageFunction.TYPE, value.itemDamage(), defaultItemDamage)
.writeOptional("bypassed_by", Types.TAG_KEY, value.bypassedByTag() != null ? Key.of(value.bypassedByTag()) : null)
.writeOptional("bypassed_by", Types.TAG_KEY, value.bypassedBy() != null ? Key.of(value.bypassedBy().tagKey()) : null)
.writeOptional("block_sound", Types.SOUND_EVENT, value.blockSound())
.writeOptional("disabled_sound", Types.SOUND_EVENT, value.disableSound()));
}
};
public static final Type<BlocksAttacks> TYPE26_1 = new Type<>(BlocksAttacks.class) {
@Override
public BlocksAttacks read(final ByteBuf buffer) {
final float blockDelaySeconds = buffer.readFloat();
final float disableCooldownScale = buffer.readFloat();
final DamageReduction[] damageReductions = DamageReduction.ARRAY_TYPE.read(buffer);
final ItemDamageFunction itemDamage = ItemDamageFunction.TYPE.read(buffer);
final HolderSet bypassedByTag = Types.OPTIONAL_HOLDER_SET.read(buffer);
final Holder<SoundEvent> blockSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
final Holder<SoundEvent> disableSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
return new BlocksAttacks(blockDelaySeconds, disableCooldownScale, damageReductions, itemDamage, bypassedByTag, blockSound, disableSound);
}
@Override
public void write(final ByteBuf buffer, final BlocksAttacks value) {
buffer.writeFloat(value.blockDelaySeconds());
buffer.writeFloat(value.disableCooldownScale());
DamageReduction.ARRAY_TYPE.write(buffer, value.damageReductions());
ItemDamageFunction.TYPE.write(buffer, value.itemDamage());
Types.OPTIONAL_HOLDER_SET.write(buffer, value.bypassedBy());
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.blockSound());
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.disableSound());
}
@Override
public void write(final Ops ops, final BlocksAttacks value) {
final DamageReduction[] defaultDamageReductions = {new DamageReduction(90, null, 0, 1)};
final ItemDamageFunction defaultItemDamage = new ItemDamageFunction(1, 0, 1);
ops.writeMap(map -> map
.writeOptional("block_delay_seconds", Types.FLOAT, value.blockDelaySeconds(), 0F)
.writeOptional("disable_cooldown_scale", Types.FLOAT, value.disableCooldownScale(), 1F)
.writeOptional("damage_reductions", DamageReduction.ARRAY_TYPE, value.damageReductions(), defaultDamageReductions)
.writeOptional("item_damage", ItemDamageFunction.TYPE, value.itemDamage(), defaultItemDamage)
.writeOptional("bypassed_by", Types.HOLDER_SET, value.bypassedBy())
.writeOptional("block_sound", Types.SOUND_EVENT, value.blockSound())
.writeOptional("disabled_sound", Types.SOUND_EVENT, value.disableSound()));
}
@@ -92,7 +132,7 @@ public record BlocksAttacks(
public BlocksAttacks rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> blockSound = SoundEvent.rewriteHolder(this.blockSound, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> disableSound = SoundEvent.rewriteHolder(this.disableSound, Rewritable.soundRewriteFunction(protocol, clientbound));
return new BlocksAttacks(this.blockDelaySeconds, this.disableCooldownScale, this.damageReductions, this.itemDamage, this.bypassedByTag, blockSound, disableSound);
return new BlocksAttacks(this.blockDelaySeconds, this.disableCooldownScale, this.damageReductions, this.itemDamage, this.bypassedBy, blockSound, disableSound);
}
public record DamageReduction(float horizontalBlockingAngle, @Nullable HolderSet type, float base, float factor) {
@@ -59,7 +59,7 @@ public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration nar
public ChatTypeDecoration read(final ByteBuf buffer) {
final String translationKey = Types.STRING.read(buffer);
final int[] parameters = Types.INT_ARRAY_PRIMITIVE.read(buffer);
final Tag style = Types.TAG.read(buffer);
final Tag style = Types.TRUSTED_TAG.read(buffer);
return new ChatTypeDecoration(translationKey, parameters, style);
}
@@ -67,7 +67,7 @@ public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration nar
public void write(final ByteBuf buffer, final ChatTypeDecoration value) {
Types.STRING.write(buffer, value.translationKey());
Types.INT_ARRAY_PRIMITIVE.write(buffer, value.parameters());
Types.TAG.write(buffer, value.style());
Types.TRUSTED_TAG.write(buffer, value.style());
}
};
@@ -44,7 +44,7 @@ public final class ContainterContents {
ops.writeList(list -> {
for (int i = 0; i < value.length; i++) {
final Item item = value[i];
if (item.isEmpty()) {
if (item == null || item.isEmpty()) {
continue;
}
@@ -28,12 +28,12 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
public record DamageResistant(Key typesTagKey) {
public record DamageResistant1_21_2(Key typesTagKey) {
public static final Type<DamageResistant> TYPE = new TransformingType<>(Types.IDENTIFIER, DamageResistant.class, DamageResistant::new, DamageResistant::typesTagKey) {
public static final Type<DamageResistant1_21_2> TYPE = new TransformingType<>(Types.IDENTIFIER, DamageResistant1_21_2.class, DamageResistant1_21_2::new, DamageResistant1_21_2::typesTagKey) {
@Override
public void write(final Ops ops, final DamageResistant value) {
public void write(final Ops ops, final DamageResistant1_21_2 value) {
ops.writeMap(map -> map.write("types", Types.TAG_KEY, value.typesTagKey));
}
};
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
public record DamageResistant26_1(HolderSet types) {
public static final Type<DamageResistant26_1> TYPE = new TransformingType<>(Types.HOLDER_SET, DamageResistant26_1.class, DamageResistant26_1::new, DamageResistant26_1::types) {
@Override
public void write(final Ops ops, final DamageResistant26_1 value) {
ops.writeMap(map -> map.write("types", Types.HOLDER_SET, value.types));
}
};
}
@@ -28,7 +28,12 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.EitherType;
import com.viaversion.viaversion.util.Either;
/**
* 1.21.11-only damage type.
*
* @param id registry int or string id
*/
public record DamageType(Either<Integer, String> id) {
public static final Type<DamageType> TYPE = TransformingType.of(new EitherType<>(Types.VAR_INT, Types.STRING), DamageType.class, DamageType::new, DamageType::id);
public static final Type<DamageType> TYPE1_21_11 = TransformingType.of(new EitherType<>(Types.VAR_INT, Types.STRING), DamageType.class, DamageType::new, DamageType::id);
}
@@ -53,6 +53,6 @@ public final class EnumTypes {
// Hardcoded registries
public static final RegistryValueType VILLAGER_TYPE = new RegistryValueType(Key.of("villager_type"), "desert", "jungle", "plains", "savanna", "snow", "swamp", "taiga");
public static final RegistryValueType POTION = new RegistryValueType(Key.of("potion"), "water", "mundane", "thick", "awkward", "night_vision", "long_night_vision", "invisibility", "long_invisibility", "leaping", "long_leaping", "strong_leaping", "fire_resistance", "long_fire_resistance", "swiftness", "long_swiftness", "strong_swiftness", "slowness", "long_slowness", "strong_slowness", "turtle_master", "long_turtle_master", "strong_turtle_master", "water_breathing", "long_water_breathing", "healing", "strong_healing", "harming", "strong_harming", "poison", "long_poison", "strong_poison", "regeneration", "long_regeneration", "strong_regeneration", "strength", "long_strength", "strong_strength", "weakness", "long_weakness", "luck", "slow_falling", "long_slow_falling", "wind_charged", "weaving", "oozing", "infested");
public static final RegistryValueType MOB_EFFECT = new RegistryValueType(Key.of("mob_effect"), "speed", "slowness", "haste", "mining_fatigue", "strength", "instant_health", "instant_damage", "jump_boost", "nausea", "regeneration", "resistance", "fire_resistance", "water_breathing", "invisibility", "blindness", "night_vision", "hunger", "weakness", "poison", "wither", "health_boost", "absorption", "saturation", "glowing", "levitation", "luck", "unluck", "slow_falling", "conduit_power", "dolphins_grace", "bad_omen", "hero_of_the_village", "darkness", "trial_omen", "raid_omen", "wind_charged", "weaving", "oozing", "infested");
public static final RegistryValueType MOB_EFFECT = new RegistryValueType(Key.of("mob_effect"), "speed", "slowness", "haste", "mining_fatigue", "strength", "instant_health", "instant_damage", "jump_boost", "nausea", "regeneration", "resistance", "fire_resistance", "water_breathing", "invisibility", "blindness", "night_vision", "hunger", "weakness", "poison", "wither", "health_boost", "absorption", "saturation", "glowing", "levitation", "luck", "unluck", "slow_falling", "conduit_power", "dolphins_grace", "bad_omen", "hero_of_the_village", "darkness", "trial_omen", "raid_omen", "wind_charged", "weaving", "oozing", "infested", "breath_of_the_nautilus");
public static final RegistryValueType CONSUME_EFFECT = new RegistryValueType(Key.of("consume_effect_type"), "apply_effects", "remove_effects", "clear_all_effects", "teleport_randomly", "play_sound");
}
@@ -0,0 +1,34 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.RegistryKey;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
public record ProvidesBannerPatterns(HolderSet patterns) {
public static final Type<ProvidesBannerPatterns> TYPE = TransformingType.of(new HolderSetType(RegistryKey.of("banner_pattern")), ProvidesBannerPatterns.class, ProvidesBannerPatterns::new, ProvidesBannerPatterns::patterns);
}
@@ -79,7 +79,7 @@ public interface ViaInjector {
}
/**
* Get the name of the encoder for then netty pipeline for this platform.
* Get the name of the encoder for the netty pipeline for this platform.
*
* @return The name
*/
@@ -88,7 +88,7 @@ public interface ViaInjector {
}
/**
* Get the name of the decoder for then netty pipeline for this platform.
* Get the name of the decoder for the netty pipeline for this platform.
*
* @return The name
*/
@@ -165,6 +165,30 @@ public interface ViaPlatform<T> {
return false;
}
/**
* Modify the player details payload before it is sent.
* This method allows adding, changing, or removing fields from the payload.
* It is only called if {@link ViaVersionConfig#sendPlayerDetails()} is true.
*
* @param connection The UserConnection
* @param payload The constructed payload to modify
*/
default void modifyPlayerDetails(UserConnection connection, JsonObject payload) {
// To be overridden if needed
}
/**
* Modify the server details payload before it is sent.
* This method allows adding, changing, or removing fields from the payload.
* It is only called if {@link ViaVersionConfig#sendPlayerDetails()} is true.
*
* @param connection The UserConnection
* @param payload The constructed payload to modify
*/
default void modifyServerDetails(UserConnection connection, JsonObject payload) {
// To be overridden if needed
}
/**
* Send a custom payload to from a player to the server.
*
@@ -328,6 +328,13 @@ public interface PacketWrapper {
*/
void resetReader();
/**
* Rewind the reader by the given number of arguments, so they can be read again.
*
* @param values number of values to add to the reader dequeue again
*/
void rewindReader(int values);
/**
* 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>
@@ -382,12 +389,21 @@ public interface PacketWrapper {
*/
void scheduleSendToServer(Class<? extends Protocol> protocol, boolean skipCurrentPipeline) throws InformativeException;
/**
* Allows running through code that may both read and write data to/from this packet wrapper,
* but will no-op any write call.
*
* @param runnable runnable to do further method calls on this packet wrapper
*/
void consumeReadsOnly(Runnable runnable);
/**
* Returns the packet type, or null if not transformed or manually unset.
*
* @return packet type if set
*/
@Nullable PacketType getPacketType();
@Nullable
PacketType getPacketType();
/**
* Sets the packet type. If set to null, it will not be written to the buffer with {@link #writeToBuffer(ByteBuf)}.
@@ -93,6 +93,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_21_7 = register(772, "1.21.7-1.21.8", new SubVersionRange("1.21", 7, 8));
public static final ProtocolVersion v1_21_9 = register(773, "1.21.9-1.21.10", new SubVersionRange("1.21", 9, 10));
public static final ProtocolVersion v1_21_11 = register(774, "1.21.11");
public static final ProtocolVersion v26_1 = register(775, "26.1");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -27,9 +27,10 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Wrapper class file for {@link com.google.common.collect.Range} to support multiple ranges. This class is used to
* Wrapper class file for {@link Range} to support multiple ranges. This class is used to
* compare {@link ProtocolVersion} objects.
*/
public class ProtocolVersionRange {
@@ -43,7 +44,7 @@ public class ProtocolVersionRange {
}
/**
* Returns a range that contains all versions.
* Returns a range that contains all versions. Adding new ranges to this range is not supported.
*
* @return the range
*/
@@ -159,6 +160,46 @@ public class ProtocolVersionRange {
return false;
}
/**
* Gets the minimum version in this range. If there are multiple ranges, the lowest minimum is returned.
*
* @return the minimum version, or null if there is no minimum
*/
public @Nullable ProtocolVersion getMin() {
ProtocolVersion min = null;
if (this.ranges != null) {
for (Range<ProtocolVersion> range : this.ranges) {
if (range.hasLowerBound()) {
ProtocolVersion rangeMin = range.lowerEndpoint();
if (min == null || rangeMin.compareTo(min) < 0) {
min = rangeMin;
}
}
}
}
return min;
}
/**
* Gets the maximum version in this range. If there are multiple ranges, the highest maximum is returned.
*
* @return the maximum version, or null if there is no maximum
*/
public @Nullable ProtocolVersion getMax() {
ProtocolVersion max = null;
if (this.ranges != null) {
for (Range<ProtocolVersion> range : this.ranges) {
if (range.hasUpperBound()) {
ProtocolVersion rangeMax = range.upperEndpoint();
if (max == null || rangeMax.compareTo(max) > 0) {
max = rangeMax;
}
}
}
}
return max;
}
@Override
public String toString() {
if (this.ranges != null) {
@@ -197,7 +238,7 @@ public class ProtocolVersionRange {
}
/**
* Parses a range from a string.
* Parses a range from a string generated by {@link #toString()}.
*
* @param str the string
* @return the range
@@ -102,6 +102,16 @@ public interface ItemRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter<T
return itemArrayType();
}
@Nullable
default Type<Item> itemTemplateType() {
return itemType();
}
@Nullable
default Type<Item> mappedItemTemplateType() {
return mappedItemType();
}
/**
* Returns the NBT tag name used for storing original item data.
*
@@ -22,10 +22,17 @@
*/
package com.viaversion.viaversion.api.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.util.KeyMappings;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface RegistryDataRewriter {
@Nullable KeyMappings getMappings(String registryKey);
@Nullable
KeyMappings getMappings(String registryKey);
boolean shouldRemoveRegistry(String registryKey);
void updateDialog(UserConnection connection, CompoundTag tag);
}
@@ -103,10 +103,11 @@ import com.viaversion.viaversion.api.type.types.math.BlockPositionType1_8;
import com.viaversion.viaversion.api.type.types.math.ChunkPositionType;
import com.viaversion.viaversion.api.type.types.math.EulerAngleType;
import com.viaversion.viaversion.api.type.types.math.GlobalBlockPositionType;
import com.viaversion.viaversion.api.type.types.math.MovementVectorType;
import com.viaversion.viaversion.api.type.types.math.LowPrecisionVectorType;
import com.viaversion.viaversion.api.type.types.math.QuaternionType;
import com.viaversion.viaversion.api.type.types.math.Vector3fType;
import com.viaversion.viaversion.api.type.types.math.VectorType;
import com.viaversion.viaversion.api.type.types.misc.CompoundTagHolderType;
import com.viaversion.viaversion.api.type.types.misc.CompoundTagType;
import com.viaversion.viaversion.api.type.types.misc.GameProfileType;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
@@ -117,8 +118,8 @@ import com.viaversion.viaversion.api.type.types.misc.NamedCompoundTagType;
import com.viaversion.viaversion.api.type.types.misc.PlayerMessageSignatureType;
import com.viaversion.viaversion.api.type.types.misc.ProfileKeyType;
import com.viaversion.viaversion.api.type.types.misc.ProfilePropertyType;
import com.viaversion.viaversion.api.type.types.misc.SoundEventType;
import com.viaversion.viaversion.api.type.types.misc.ResolvableProfileType;
import com.viaversion.viaversion.api.type.types.misc.SoundEventType;
import com.viaversion.viaversion.api.type.types.misc.TagKeyType;
import com.viaversion.viaversion.api.type.types.misc.TagType;
import com.viaversion.viaversion.api.type.types.misc.TextComponentTagType;
@@ -198,19 +199,28 @@ public final class Types {
public static final Type<Vector> VECTOR = new VectorType();
public static final Type<Vector3f> VECTOR3F = new Vector3fType();
public static final Type<Quaternion> QUATERNION = new QuaternionType();
public static final Type<Vector3d> MOVEMENT_VECTOR = new MovementVectorType();
public static final Type<Vector3d> LOW_PRECISION_VECTOR = new LowPrecisionVectorType();
@Deprecated(forRemoval = true)
public static final Type<Vector3d> MOVEMENT_VECTOR = LOW_PRECISION_VECTOR;
public static final Type<CompoundTag> NAMED_COMPOUND_TAG = new NamedCompoundTagType();
public static final Type<CompoundTag> OPTIONAL_NAMED_COMPOUND_TAG = new NamedCompoundTagType.OptionalNamedCompoundTagType();
public static final Type<CompoundTag[]> NAMED_COMPOUND_TAG_ARRAY = new ArrayType<>(Types.NAMED_COMPOUND_TAG);
public static final Type<CompoundTag> COMPOUND_TAG = new CompoundTagType();
public static final Type<CompoundTag> OPTIONAL_COMPOUND_TAG = new CompoundTagType.OptionalCompoundTagType();
public static final Type<CompoundTag> OPTIONAL_COMPOUND_TAG = CompoundTagType.OptionalCompoundTagType.type();
public static final HolderType<CompoundTag> TRUSTED_COMPOUND_TAG_HOLDER = new CompoundTagHolderType();
public static final Type<Tag> TAG = new TagType();
public static final Type<Tag[]> TAG_ARRAY = new ArrayType<>(TAG);
public static final Type<Tag> OPTIONAL_TAG = new TagType.OptionalTagType();
public static final Type<Tag> OPTIONAL_TAG = TagType.OptionalTagType.type();
public static final Type<Tag> TEXT_COMPONENT_TAG = new TextComponentTagType(); // only strictly needed for hashing
public static final Type<Tag> CUSTOM_CLICK_ACTION_TAG = new LengthPrefixedTagType(65536);
public static final Type<Tag> TRUSTED_TAG = new TagType(false);
public static final Type<Tag> TRUSTED_OPTIONAL_TAG = TagType.OptionalTagType.trustedType();
public static final Type<CompoundTag> TRUSTED_COMPOUND_TAG = new CompoundTagType(false);
public static final Type<CompoundTag> TRUSTED_OPTIONAL_COMPOUND_TAG = CompoundTagType.OptionalCompoundTagType.trustedType();
public static final Type<GlobalBlockPosition> GLOBAL_POSITION = new GlobalBlockPositionType();
public static final Type<GlobalBlockPosition> OPTIONAL_GLOBAL_POSITION = new GlobalBlockPositionType.OptionalGlobalPositionType();
public static final Type<ChunkPosition> CHUNK_POSITION = new ChunkPositionType();
@@ -28,13 +28,21 @@ import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public class VarIntArrayType extends Type<int[]> {
public VarIntArrayType() {
private final int length;
public VarIntArrayType(final int length) {
super(int[].class);
this.length = length;
}
public VarIntArrayType() {
this(-1);
}
@Override
public int[] read(ByteBuf buffer) {
int length = Types.VAR_INT.readPrimitive(buffer);
int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length)); // Sanity check, at least 1 byte will be used for each varint
int[] array = new int[length];
for (int i = 0; i < array.length; i++) {
@@ -45,7 +53,11 @@ public class VarIntArrayType extends Type<int[]> {
@Override
public void write(ByteBuf buffer, int[] object) {
Types.VAR_INT.writePrimitive(buffer, object.length);
if (this.length != -1) {
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
} else {
Types.VAR_INT.writePrimitive(buffer, object.length);
}
for (int i : object) {
Types.VAR_INT.writePrimitive(buffer, i);
}
@@ -31,8 +31,8 @@ import io.netty.buffer.ByteBuf;
public class ChunkSectionType1_18 extends Type<ChunkSection> {
private final PaletteTypeBase blockPaletteType;
private final PaletteTypeBase biomePaletteType;
protected final PaletteTypeBase blockPaletteType;
protected final PaletteTypeBase biomePaletteType;
public ChunkSectionType1_18(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(ChunkSection.class);
@@ -0,0 +1,68 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
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 io.netty.buffer.ByteBuf;
public class ChunkSectionType26_1 extends ChunkSectionType1_18 {
public ChunkSectionType26_1(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(
new PaletteType1_21_5(PaletteType.BLOCKS, globalPaletteBlockBits),
new PaletteType1_21_5(PaletteType.BIOMES, globalPaletteBiomeBits)
);
}
@Override
public ChunkSection read(final ByteBuf buffer) {
final ChunkSection chunkSection = new ChunkSectionImpl();
chunkSection.setNonAirBlocksCount(buffer.readShort());
chunkSection.setFluidCount(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) {
buffer.writeShort(section.getNonAirBlocksCount());
buffer.writeShort(section.getFluidCount());
blockPaletteType.write(buffer, section.palette(PaletteType.BLOCKS));
biomePaletteType.write(buffer, section.palette(PaletteType.BIOMES));
}
@Override
public int serializedSize(final Chunk chunk) {
int length = 0;
for (final ChunkSection section : chunk.getSections()) {
length += Short.BYTES + Short.BYTES // non-air and fluid count
+ blockPaletteType.serializedSize(section.palette(PaletteType.BLOCKS))
+ biomePaletteType.serializedSize(section.palette(PaletteType.BIOMES));
}
return length;
}
}
@@ -34,14 +34,18 @@ import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class ChunkType1_21_5 extends Type<Chunk> {
public class ChunkType1_21_5 extends Type<Chunk> {
private final ChunkSectionType1_18 sectionType;
private final int ySectionCount;
public ChunkType1_21_5(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
this(new ChunkSectionType1_21_5(globalPaletteBlockBits, globalPaletteBiomeBits), ySectionCount);
}
protected ChunkType1_21_5(final ChunkSectionType1_18 sectionType, final int ySectionCount) {
super(Chunk.class);
Preconditions.checkArgument(ySectionCount > 0);
this.sectionType = new ChunkSectionType1_21_5(globalPaletteBlockBits, globalPaletteBiomeBits);
this.sectionType = sectionType;
this.ySectionCount = ySectionCount;
}
@@ -0,0 +1,30 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
public final class ChunkType26_1 extends ChunkType1_21_5 {
public ChunkType26_1(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(new ChunkSectionType26_1(globalPaletteBlockBits, globalPaletteBiomeBits), ySectionCount);
}
}
@@ -0,0 +1,64 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.item;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.StructuredItemTemplate;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.util.Map;
// Holds the same exact data as a regular item stack
public class ItemTemplateType26_1 extends ItemType1_20_5 {
public ItemTemplateType26_1(final StructuredDataTypeBase dataType) {
super(dataType);
}
@Override
public Item read(final ByteBuf buffer) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final int amount = Types.VAR_INT.readPrimitive(buffer);
final Map<StructuredDataKey<?>, StructuredData<?>> data = readData(buffer);
return new StructuredItemTemplate(id, amount, new StructuredDataContainer(data));
}
@Override
public void write(final ByteBuf buffer, final Item object) {
Types.VAR_INT.writePrimitive(buffer, object.identifier());
Types.VAR_INT.writePrimitive(buffer, object.amount());
writeData(buffer, object);
}
public static final class OptionalItemTemplateType extends OptionalType<Item> {
public OptionalItemTemplateType(final Type<Item> type) {
super(type);
}
}
}
@@ -58,7 +58,7 @@ public class ItemType1_20_5 extends Type<Item> {
return new StructuredItem(id, amount, new StructuredDataContainer(data));
}
private Map<StructuredDataKey<?>, StructuredData<?>> readData(final ByteBuf buffer) {
protected Map<StructuredDataKey<?>, StructuredData<?>> readData(final ByteBuf buffer) {
final int valuesSize = Types.VAR_INT.readPrimitive(buffer);
final int markersSize = Types.VAR_INT.readPrimitive(buffer);
if (valuesSize == 0 && markersSize == 0) {
@@ -92,6 +92,10 @@ public class ItemType1_20_5 extends Type<Item> {
Types.VAR_INT.writePrimitive(buffer, object.amount());
Types.VAR_INT.writePrimitive(buffer, object.identifier());
writeData(buffer, object);
}
protected void writeData(final ByteBuf buffer, final Item object) {
final Map<StructuredDataKey<?>, StructuredData<?>> data = object.dataContainer().data();
int valuesSize = 0;
int markersSize = 0;
@@ -29,7 +29,7 @@ import com.viaversion.viaversion.api.type.types.UnsignedIntType;
import com.viaversion.viaversion.util.MathUtil;
import io.netty.buffer.ByteBuf;
public class MovementVectorType extends Type<Vector3d> {
public class LowPrecisionVectorType extends Type<Vector3d> {
// Using 15 bits, steal short constants for it
private static final double MAX_QUANTIZED_VALUE = Short.MAX_VALUE - 1;
private static final int SCALE_BITS = 2; // first 2 bits for the scale
@@ -38,7 +38,7 @@ public class MovementVectorType extends Type<Vector3d> {
private static final double ABS_MAX_VALUE = (1L << Integer.SIZE + SCALE_BITS) - 1; // Unsigned int + the first two scale bits
private static final double ABS_MIN_VALUE = 1 / MAX_QUANTIZED_VALUE;
public MovementVectorType() {
public LowPrecisionVectorType() {
super(Vector3d.class);
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.misc;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public final class CompoundTagHolderType extends HolderType<CompoundTag> {
@Override
public CompoundTag readDirect(final ByteBuf buffer) {
return Types.TRUSTED_COMPOUND_TAG.read(buffer);
}
@Override
public void writeDirect(final ByteBuf buffer, final CompoundTag value) {
Types.TRUSTED_COMPOUND_TAG.write(buffer, value);
}
}
@@ -41,14 +41,21 @@ import java.util.Map;
*/
public class CompoundTagType extends Type<CompoundTag> {
private final int maxBytes;
public CompoundTagType() {
this(true);
}
public CompoundTagType(final boolean limitMaxBytes) {
super(CompoundTag.class);
this.maxBytes = limitMaxBytes ? NamedCompoundTagType.MAX_NBT_BYTES : Integer.MAX_VALUE;
}
@Override
public CompoundTag read(final ByteBuf buffer) {
try {
return NamedCompoundTagType.read(buffer, false);
return NamedCompoundTagType.read(buffer, this.maxBytes, false);
} catch (final IOException e) {
throw new RuntimeException(e);
}
@@ -74,8 +81,16 @@ public class CompoundTagType extends Type<CompoundTag> {
public static final class OptionalCompoundTagType extends OptionalType<CompoundTag> {
public OptionalCompoundTagType() {
super(Types.COMPOUND_TAG);
private OptionalCompoundTagType(final Type<CompoundTag> tagType) {
super(tagType);
}
public static OptionalCompoundTagType type() {
return new OptionalCompoundTagType(Types.COMPOUND_TAG);
}
public static OptionalCompoundTagType trustedType() {
return new OptionalCompoundTagType(Types.TRUSTED_COMPOUND_TAG);
}
}
}
@@ -29,6 +29,11 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
/**
* Mess for certain pre 26.1 things.
*
* @param <T> held type
*/
public final class EitherHolderType<T> extends Type<EitherHolder<T>> {
private final HolderType<T> holderType;
@@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.VarIntArrayType;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
@@ -58,12 +59,7 @@ public class HolderSetType extends Type<HolderSet> {
final String tag = Types.STRING.read(buffer);
return HolderSet.of(tag);
}
final int[] values = new int[size];
for (int i = 0; i < size; i++) {
values[i] = Types.VAR_INT.readPrimitive(buffer);
}
return HolderSet.of(values);
return HolderSet.of(new VarIntArrayType(size).read(buffer));
}
@Override
@@ -46,7 +46,7 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
@Override
public CompoundTag read(final ByteBuf buffer) {
try {
return read(buffer, true);
return read(buffer, MAX_NBT_BYTES, true);
} catch (final IOException e) {
throw new RuntimeException(e);
}
@@ -61,7 +61,7 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
}
}
public static CompoundTag read(final ByteBuf buffer, final boolean readName) throws IOException {
public static CompoundTag read(final ByteBuf buffer, final int maxBytes, final boolean readName) throws IOException {
final byte id = buffer.readByte();
if (id == 0) {
return null;
@@ -74,7 +74,7 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
buffer.skipBytes(buffer.readUnsignedShort());
}
final TagLimiter tagLimiter = TagLimiter.create(MAX_NBT_BYTES, MAX_NESTING_LEVEL);
final TagLimiter tagLimiter = TagLimiter.create(maxBytes, MAX_NESTING_LEVEL);
return CompoundTag.read(new ByteBufInputStream(buffer), tagLimiter, 0);
}
@@ -50,8 +50,15 @@ import java.util.Map;
public class TagType extends Type<Tag> {
private final int maxBytes;
public TagType() {
this(true);
}
public TagType(final boolean limitBytes) {
super(Tag.class);
this.maxBytes = limitBytes ? NamedCompoundTagType.MAX_NBT_BYTES : Integer.MAX_VALUE;
}
@Override
@@ -61,7 +68,7 @@ public class TagType extends Type<Tag> {
return null;
}
final TagLimiter tagLimiter = TagLimiter.create(NamedCompoundTagType.MAX_NBT_BYTES, NamedCompoundTagType.MAX_NESTING_LEVEL);
final TagLimiter tagLimiter = TagLimiter.create(this.maxBytes, NamedCompoundTagType.MAX_NESTING_LEVEL);
try {
return TagRegistry.read(id, new ByteBufInputStream(buffer), tagLimiter, 0);
} catch (final IOException e) {
@@ -127,8 +134,16 @@ public class TagType extends Type<Tag> {
public static final class OptionalTagType extends OptionalType<Tag> {
public OptionalTagType() {
super(Types.TAG);
private OptionalTagType(final Type<Tag> tagType) {
super(tagType);
}
public static OptionalTagType type() {
return new OptionalTagType(Types.TAG);
}
public static OptionalTagType trustedType() {
return new OptionalTagType(Types.TRUSTED_TAG);
}
}
}
@@ -50,7 +50,7 @@ public class Types1_20_5<K extends VersionedStructuredDataKeys, E extends Abstra
public final Type<Item[]> itemArray = new ArrayType<>(item);
public final Type<Item> itemCost = new ItemCostType1_20_5(structuredDataArray);
public final Type<Item> optionalItemCost = new ItemCostType1_20_5.OptionalItemCostType(itemCost);
public final K structuredDataKeys;
private K structuredDataKeys;
public final ParticleType particle = new ParticleType();
public final ArrayType<Particle> particles = new ArrayType<>(particle);
@@ -58,11 +58,17 @@ public class Types1_20_5<K extends VersionedStructuredDataKeys, E extends Abstra
public final Type<EntityData> entityData;
public final Type<List<EntityData>> entityDataList;
public Types1_20_5(final Function<Types1_20_5<?, ?>, K> keysSupplier, final Function<Types1_20_5<?, ?>, E> entityDataTypesSupplier) {
this.structuredDataKeys = keysSupplier.apply(this);
public Types1_20_5(final Function<VersionedTypesHolder, K> keysSupplier, final Function<VersionedTypesHolder, E> entityDataTypesSupplier) {
this.entityDataTypes = entityDataTypesSupplier.apply(this);
this.entityData = new EntityDataType(entityDataTypes);
this.entityDataList = new EntityDataListType(entityData);
if (keysSupplier != null) {
initKeys(keysSupplier);
}
}
protected void initKeys(final Function<VersionedTypesHolder, K> keysSupplier) {
this.structuredDataKeys = keysSupplier.apply(this);
}
@Override
@@ -75,6 +81,21 @@ public class Types1_20_5<K extends VersionedStructuredDataKeys, E extends Abstra
return itemArray;
}
@Override
public Type<Item> itemTemplate() {
return item;
}
@Override
public Type<Item> optionalItemTemplate() {
return item;
}
@Override
public Type<Item[]> itemTemplateArray() {
return itemArray;
}
@Override
public Type<Item> itemCost() {
return itemCost;
@@ -34,7 +34,7 @@ public final class Types1_21 extends Types1_20_5<StructuredDataKeys1_20_5, Entit
public final Type<Item> optionalItem; // Optional as in boolean prefixed, not via the amount
public Types1_21(final Function<Types1_20_5<?, ?>, StructuredDataKeys1_20_5> keysSupplier, final Function<Types1_20_5<?, ?>, EntityDataTypes1_21> entityDataTypesSupplier) {
public Types1_21(final Function<VersionedTypesHolder, StructuredDataKeys1_20_5> keysSupplier, final Function<VersionedTypesHolder, EntityDataTypes1_21> entityDataTypesSupplier) {
super(keysSupplier, entityDataTypesSupplier);
this.optionalItem = ((ItemType1_20_5) item).new OptionalItemType();
}
@@ -0,0 +1,58 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.data.version.VersionedStructuredDataKeys;
import com.viaversion.viaversion.api.minecraft.entitydata.types.AbstractEntityDataTypes;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.item.ItemTemplateType26_1;
import java.util.function.Function;
public class Types26_1<K extends VersionedStructuredDataKeys, E extends AbstractEntityDataTypes> extends Types1_20_5<K, E> {
public final Type<Item> itemTemplate = new ItemTemplateType26_1(structuredData);
public final Type<Item> optionalItemTemplate = new ItemTemplateType26_1.OptionalItemTemplateType(itemTemplate);
public final Type<Item[]> itemTemplateArray = new ArrayType<>(itemTemplate);
public Types26_1(final Function<VersionedTypesHolder, K> keysSupplier, final Function<VersionedTypesHolder, E> entityDataTypesSupplier) {
super(null, entityDataTypesSupplier);
initKeys(keysSupplier);
}
@Override
public Type<Item> itemTemplate() {
return itemTemplate;
}
@Override
public Type<Item> optionalItemTemplate() {
return optionalItemTemplate;
}
@Override
public Type<Item[]> itemTemplateArray() {
return itemTemplateArray;
}
}
@@ -32,6 +32,7 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_2;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
/**
* Holds versioned accessors for highly volatile types, specifically around items and data components.
@@ -49,4 +50,5 @@ public final class VersionedTypes {
public static final Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_5> V1_21_6 = new Types1_20_5<>(StructuredDataKeys1_21_5::new, EntityDataTypes1_21_5::new);
public static final Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_9> V1_21_9 = new Types1_20_5<>(StructuredDataKeys1_21_5::new, EntityDataTypes1_21_9::new);
public static final Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes1_21_11> V1_21_11 = new Types1_20_5<>(StructuredDataKeys1_21_11::new, EntityDataTypes1_21_11::new);
public static final Types26_1<StructuredDataKeys1_21_11, EntityDataTypes26_1> V26_1 = new Types26_1<>(StructuredDataKeys1_21_11::new, EntityDataTypes26_1::new);
}
@@ -39,10 +39,31 @@ import java.util.List;
*/
public interface VersionedTypesHolder {
/**
* Returns the unmapped item stack type
*
* @return unmapped item stack type
*/
Type<Item> item();
Type<Item[]> itemArray();
/**
* Returns the unmapped item stack template type, used for certain recipes/templates in 26.1+.
*
* @return unmapped item stack template type
*/
Type<Item> itemTemplate();
Type<Item> optionalItemTemplate();
Type<Item[]> itemTemplateArray();
/**
* Returns the unmapped item cost type, used in merchant offers.
*
* @return unmapped item cost type
*/
Type<Item> itemCost();
Type<Item> optionalItemCost();
+1 -1
View File
@@ -8,7 +8,7 @@ repositories {
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.3.1")
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.4.1")
// A nice no-conflict comment for patching in downgrading
}
@@ -37,7 +37,7 @@ import java.util.List;
@ChannelHandler.Sharable
public final class BukkitEncodeHandler extends ViaEncodeHandler {
private boolean handledCompression = BukkitChannelInitializer.COMPRESSION_ENABLED_EVENT != null;
private boolean handledCompression = BukkitChannelInitializer.COMPRESSION_ENABLED_EVENT != null || Boolean.getBoolean("com.viaversion.disableLegacyCompressionReorder");
public BukkitEncodeHandler(final UserConnection connection) {
super(connection);
@@ -56,7 +56,7 @@ public final class BukkitEncodeHandler extends ViaEncodeHandler {
final ByteBuf transformedBuf = ByteBufUtil.copy(ctx.alloc(), bytebuf);
try {
final boolean needsCompression = !handledCompression && handleCompressionOrder(ctx, transformedBuf);
final boolean needsCompression = !handledCompression && connection.getProtocolInfo().compressionEnabled() && handleCompressionOrder(ctx, transformedBuf);
connection.transformClientbound(transformedBuf, CancelEncoderException::generate);
if (needsCompression) {
recompress(ctx, transformedBuf);
@@ -1,44 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.classgenerator.generated;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.handlers.BukkitDecodeHandler;
import com.viaversion.viaversion.bukkit.handlers.BukkitEncodeHandler;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.codec.MessageToMessageEncoder;
public interface HandlerSupplier {
MessageToMessageEncoder<ByteBuf> newEncodeHandler(UserConnection connection);
MessageToMessageDecoder<ByteBuf> newDecodeHandler(UserConnection connection);
final class DefaultHandlerSupplier implements HandlerSupplier {
@Override
public MessageToMessageEncoder<ByteBuf> newEncodeHandler(final UserConnection connection) {
return new BukkitEncodeHandler(connection);
}
@Override
public MessageToMessageDecoder<ByteBuf> newDecodeHandler(final UserConnection connection) {
return new BukkitDecodeHandler(connection);
}
}
}
@@ -30,7 +30,7 @@ public record CodecRegistryContext(Protocol<?, ?, ?, ?> protocol, RegistryAccess
// Generally from hardcoded, but highly variable client data
private static final Set<StructuredDataKey<?>> NOT_IMPLEMENTED = new ReferenceOpenHashSet<>(List.of(
StructuredDataKey.DAMAGE_TYPE
StructuredDataKey.DAMAGE_TYPE1_21_11
));
public CodecRegistryContext(final Protocol<?, ?, ?, ?> protocol, final RegistryAccess registryAccess, final boolean mapped) {
@@ -22,9 +22,11 @@ import java.util.Arrays;
public final class HashBuilder {
private static final byte[] EMPTY_BYTES = new byte[0];
private static final int MAX_RETAINED_CAPACITY = 4096;
private final HashFunction hashFunction;
private byte[] bytes = EMPTY_BYTES;
private int index;
private boolean direct;
public HashBuilder(final HashFunction hashFunction) {
this.hashFunction = hashFunction;
@@ -43,11 +45,17 @@ public final class HashBuilder {
return this;
}
/**
* Writes the given bytes directly, avoiding a copy if currently empty.
*
* @param bytes the bytes to write directly
*/
public void writeBytesDirect(final byte[] bytes) {
if (this.bytes.length == 0) {
// Set bytes directly if still empty
this.bytes = bytes;
this.index = bytes.length;
this.direct = true;
} else {
writeBytes(bytes);
}
@@ -75,9 +83,11 @@ public final class HashBuilder {
public HashBuilder writeString(final CharSequence sequence) {
final int length = sequence.length();
this.ensureSize(length);
this.ensureSize(length * 2);
for (int i = 0; i < length; i++) {
this.writeChar(sequence.charAt(i));
final char c = sequence.charAt(i);
this.bytes[this.index++] = (byte) c;
this.bytes[this.index++] = (byte) (c >> 8);
}
return this;
}
@@ -130,9 +140,11 @@ public final class HashBuilder {
private void ensureSize(final int bytes) {
final int length = this.bytes.length;
if (this.index + bytes > length) {
final int newLength = Math.max(length * 2, this.index + bytes);
final int required = this.index + bytes;
if (required > length) {
final int newLength = Math.max(length * 2, required);
this.bytes = Arrays.copyOf(this.bytes, newLength);
this.direct = false;
}
}
@@ -142,7 +154,11 @@ public final class HashBuilder {
public void reset() {
this.index = 0;
this.bytes = EMPTY_BYTES;
// Discard the buffer if it was direct (externally owned) or exceeds max retained capacity
if (this.direct || this.bytes.length > MAX_RETAINED_CAPACITY) {
this.bytes = EMPTY_BYTES;
this.direct = false;
}
}
public HashFunction function() {
@@ -37,6 +37,11 @@ public class DebugSubCmd implements ViaSubCommand {
return "Toggle various debug modes.";
}
@Override
public String usage() {
return "debug [clear|pre|post], or debug <add|remove> <packet>";
}
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
final DebugHandler debug = Via.getManager().debugHandler();
@@ -49,11 +54,11 @@ public class DebugSubCmd implements ViaSubCommand {
debug.clearPacketTypesToLog();
sendMessage(sender, "&6Cleared packet types to log");
return true;
} else if (args[0].equalsIgnoreCase("logpretransform")) {
} else if (args[0].equalsIgnoreCase("pre")) {
debug.setLogPrePacketTransform(!debug.logPrePacketTransform());
sendMessage(sender, "&6Pre transform packet logging is now %s", (debug.logPrePacketTransform() ? "&aenabled" : "&cdisabled"));
return true;
} else if (args[0].equalsIgnoreCase("logposttransform")) {
} else if (args[0].equalsIgnoreCase("post")) {
debug.setLogPostPacketTransform(!debug.logPostPacketTransform());
sendMessage(sender, "&6Post transform packet logging is now %s", (debug.logPostPacketTransform() ? "&aenabled" : "&cdisabled"));
return true;
@@ -75,7 +80,7 @@ public class DebugSubCmd implements ViaSubCommand {
@Override
public List<String> onTabComplete(final ViaCommandSender sender, final String[] args) {
if (args.length == 1) {
return Arrays.asList("clear", "logposttransform", "add", "remove");
return Arrays.asList("clear", "pre", "post", "add", "remove");
}
return Collections.emptyList();
}
@@ -37,7 +37,7 @@ public class DisplayLeaksSubCmd implements ViaSubCommand {
@Override
public String usage() {
return "displayleaks <level>";
return "displayleaks [level]";
}
@Override
@@ -64,24 +64,21 @@ public final class ConnectionDetails {
return;
}
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
final ProtocolVersion nativeVersion = protocolInfo.protocolVersion();
final ProtocolVersion serverVersion = protocolInfo.serverProtocolVersion();
if (serverVersion.equals(nativeVersion)) {
// No need to send details if the native version is the same as the server version
return;
}
final JsonObject payload = new JsonObject();
payload.addProperty("specVersion", VERSION);
final String platformName = Via.getPlatform().getPlatformName();
final String platformVersion = Via.getPlatform().getPlatformVersion();
final JsonObject payload = new JsonObject();
payload.addProperty("specVersion", VERSION);
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
final ProtocolVersion clientVersion = protocolInfo.protocolVersion();
payload.addProperty("platformName", platformName);
payload.addProperty("platformVersion", platformVersion);
payload.addProperty("version", nativeVersion.getOriginalVersion());
payload.addProperty("versionName", nativeVersion.getName());
payload.addProperty("version", clientVersion.getOriginalVersion());
payload.addProperty("versionName", clientVersion.getName());
payload.addProperty("versionType", clientVersion.getVersionType().name());
Via.getPlatform().modifyPlayerDetails(connection, payload);
Via.getPlatform().sendCustomPayload(connection, channel, payload.toString().getBytes(StandardCharsets.UTF_8));
}
@@ -98,13 +95,15 @@ public final class ConnectionDetails {
return;
}
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
final ProtocolVersion serverVersion = protocolInfo.serverProtocolVersion();
final JsonObject payload = new JsonObject();
payload.addProperty("specVersion", VERSION);
final ProtocolInfo protocolInfo = connection.getProtocolInfo();
final ProtocolVersion serverVersion = protocolInfo.serverProtocolVersion();
payload.addProperty("version", serverVersion.getOriginalVersion());
payload.addProperty("versionName", serverVersion.getName());
payload.addProperty("versionType", serverVersion.getVersionType().name());
Via.getPlatform().modifyServerDetails(connection, payload);
Via.getPlatform().sendCustomPayloadToClient(connection, channel, payload.toString().getBytes(StandardCharsets.UTF_8));
}
@@ -32,6 +32,7 @@ public class ProtocolInfoImpl implements ProtocolInfo {
private String username;
private UUID uuid;
private ProtocolPipeline pipeline;
private boolean compressionEnabled;
@Override
public State getClientState() {
@@ -99,6 +100,16 @@ public class ProtocolInfoImpl implements ProtocolInfo {
this.uuid = uuid;
}
@Override
public boolean compressionEnabled() {
return compressionEnabled;
}
@Override
public void setCompressionEnabled(final boolean compressionEnabled) {
this.compressionEnabled = compressionEnabled;
}
@Override
public ProtocolPipeline getPipeline() {
return pipeline;
@@ -215,7 +215,7 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
@Override
public @Nullable DimensionData dimensionData(int dimensionId) {
return dimensions.values().stream().filter(data -> data.id() == dimensionId).findFirst().orElse(null); // TODO Store as array as well
return dimensions.values().stream().filter(data -> data.id() == dimensionId).findFirst().orElse(null);
}
@Override
@@ -116,6 +116,8 @@ public class ItemHasherBase implements ItemHasher {
entry.setValue(clientProvidedHash);
}
}
originalItem.setAmount(clientItem.amount());
return originalItem;
}
@@ -49,6 +49,11 @@ public abstract class UserConnectionViaVersionPlatform implements ViaPlatform<Us
@Override
public abstract Logger createLogger(String name);
@Override
public boolean isProxy() {
return true;
}
@Override
public Logger getLogger() {
return logger;
@@ -17,10 +17,13 @@
*/
package com.viaversion.viaversion.platform;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.platform.ViaInjector;
import com.viaversion.viaversion.connection.UserConnectionImpl;
import com.viaversion.viaversion.protocol.ProtocolPipelineImpl;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import java.lang.reflect.Method;
@@ -59,6 +62,30 @@ public abstract class ViaChannelInitializer extends ChannelInitializer<Channel>
return connection;
}
/**
* Reorders the ViaVersion handlers in the pipeline to be after the specified handlers. This is needed in platforms
* where enabling the compression breaks the order of Via handlers to be: encoder -> compressor -> via encoder.
*
* @param pipeline The channel pipeline
* @param compress The name of the compress handler where Via's encoder was initially placed after
* @param decompress The name of the decompress handler where Via's decoder was initially placed after
*/
public static void reorderPipeline(final ChannelPipeline pipeline, final String compress, final String decompress) {
final ViaInjector injector = Via.getManager().getInjector();
final int decompressIndex = pipeline.names().indexOf(decompress);
if (decompressIndex == -1) {
return;
}
if (decompressIndex > pipeline.names().indexOf(injector.getDecoderName())) {
final ChannelHandler encoderHandler = pipeline.remove(injector.getEncoderName());
final ChannelHandler decoderHandler = pipeline.remove(injector.getDecoderName());
pipeline.addAfter(compress, injector.getEncoderName(), encoderHandler);
pipeline.addAfter(decompress, injector.getDecoderName(), decoderHandler);
}
}
protected abstract void injectPipeline(ChannelPipeline pipeline, UserConnection connection);
@Override
@@ -76,6 +76,7 @@ import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.Protocol1_20_3To1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.Protocol1_20To1_20_2;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.Protocol1_21_11To26_1;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.Protocol1_21_4To1_21_5;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.Protocol1_21_5To1_21_6;
@@ -213,6 +214,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
registerProtocol(new Protocol1_21_6To1_21_7(), ProtocolVersion.v1_21_7, ProtocolVersion.v1_21_6);
registerProtocol(new Protocol1_21_7To1_21_9(), ProtocolVersion.v1_21_9, ProtocolVersion.v1_21_7);
registerProtocol(new Protocol1_21_9To1_21_11(), ProtocolVersion.v1_21_11, ProtocolVersion.v1_21_9);
registerProtocol(new Protocol1_21_11To26_1(), ProtocolVersion.v26_1, ProtocolVersion.v1_21_11);
}
@Override
@@ -478,6 +478,19 @@ public class PacketWrapperImpl implements PacketWrapper {
this.packetValues.clear();
}
@Override
public void rewindReader(final int values) {
if (allActionsRead) {
return;
}
final int size = packetValues.size();
Preconditions.checkArgument(values <= size, "Tried resetting more values than there are readable values");
for (int i = size - 1; i >= size - values; i--) {
this.readableObjects.addFirst(this.packetValues.remove(i));
}
}
@Override
public void sendToServerRaw() throws InformativeException {
sendToServerRaw(true);
@@ -584,6 +597,17 @@ public class PacketWrapperImpl implements PacketWrapper {
this.allActionsRead = allActionsRead;
}
@Override
public void consumeReadsOnly(final Runnable runnable) {
final boolean previous = this.allActionsRead;
this.allActionsRead = true;
try {
runnable.run();
} finally {
this.allActionsRead = previous;
}
}
@Override
public String toString() {
return "PacketWrapper{" +
@@ -128,6 +128,11 @@ public class ClientboundBaseProtocol1_7 extends AbstractProtocol<BaseClientbound
}
});
registerClientbound(ClientboundLoginPackets.LOGIN_COMPRESSION, wrapper -> {
final int threshold = wrapper.passthrough(Types.VAR_INT);
wrapper.user().getProtocolInfo().setCompressionEnabled(threshold >= 0);
});
// Track player name/uuid and setup connection + track state
registerClientbound(ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
final ProtocolInfo info = wrapper.user().getProtocolInfo();
@@ -21,24 +21,23 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.RecipeDisplayRewriter1_21_5;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import com.viaversion.viaversion.rewriter.block.BlockRewriter1_21_5;
// To replace if needed:
// ChunkType1_21_5
// ChunkType26_1
// RecipeDisplayRewriter
// Types1_21_4, Types1_OLD
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21_6, ServerboundPacket1_21_6, Protocol1_98To1_99> {
final class BlockItemPacketRewriter99_1 extends StructuredItemRewriter<ClientboundPacket26_1, ServerboundPacket1_21_9, Protocol98_1To99_1> {
public BlockItemPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
public BlockItemPacketRewriter99_1(final Protocol98_1To99_1 protocol) {
super(protocol);
}
@@ -47,32 +46,32 @@ final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Clientbou
// Register block and block state id changes
// Other places using block state id mappings: Spawn particle, entity data, entity spawn (falling blocks)
// Tags and statistics use block (!) ids
final BlockRewriter<ClientboundPacket1_21_6> blockRewriter = new BlockRewriter1_21_5<>(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21_6.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_6.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_6.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_6.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_6.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_21_5::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_6.BLOCK_ENTITY_DATA);
final BlockRewriter<ClientboundPacket26_1> blockRewriter = new BlockRewriter1_21_5<>(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets26_1.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets26_1.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets26_1.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets26_1.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets26_1.LEVEL_CHUNK_WITH_LIGHT, ChunkType26_1::new);
blockRewriter.registerBlockEntityData(ClientboundPackets26_1.BLOCK_ENTITY_DATA);
// Registers item id changes
// Other places using item ids are: Entity data, tags, statistics, effect
// registerOpenScreen(ClientboundPackets1_21_6.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
registerSetCursorItem(ClientboundPackets1_21_6.SET_CURSOR_ITEM);
registerSetPlayerInventory(ClientboundPackets1_21_6.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets1_21_6.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets1_21_6.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_6.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_6.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_6.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_6.MERCHANT_OFFERS);
// registerOpenScreen(ClientboundPackets26_1.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
registerSetCursorItem(ClientboundPackets26_1.SET_CURSOR_ITEM);
registerSetPlayerInventory(ClientboundPackets26_1.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets26_1.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets26_1.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets26_1.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets26_1.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets26_1.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets26_1.MERCHANT_OFFERS);
registerContainerClick1_21_5(ServerboundPackets1_21_6.CONTAINER_CLICK);
registerSetCreativeModeSlot1_21_5(ServerboundPackets1_21_6.SET_CREATIVE_MODE_SLOT);
final RecipeDisplayRewriter<ClientboundPacket1_21_6> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_6.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_6.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_6.PLACE_GHOST_RECIPE);
final RecipeDisplayRewriter<ClientboundPacket26_1> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets26_1.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets26_1.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets26_1.PLACE_GHOST_RECIPE);
// OR do this if serialization of recipes changed and override the relevant method
// Add new serializers to RecipeDisplayRewriter, or extend the last one for changes
}
@@ -19,12 +19,12 @@ package com.viaversion.viaversion.protocols.template;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
final class ComponentRewriter1_99 extends NBTComponentRewriter<ClientboundPacket1_21_6> {
final class ComponentRewriter99_1 extends NBTComponentRewriter<ClientboundPacket26_1> {
public ComponentRewriter1_99(final Protocol1_98To1_99 protocol) {
public ComponentRewriter99_1(final Protocol98_1To99_1 protocol) {
super(protocol);
}
@@ -18,36 +18,36 @@
package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.rewriter.EntityRewriter;
// Replace if needed
// VersionedTypes
// EntityTypes1_21_9
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21_6, Protocol1_98To1_99> {
// EntityTypes1_21_11
final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_1, Protocol98_1To99_1> {
public EntityPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
public EntityPacketRewriter99_1(final Protocol98_1To99_1 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
// Tracks entities, applies entity data rewrites registered below, untracks entities
registerTrackerWithData1_21_9(ClientboundPackets1_21_6.ADD_ENTITY, EntityTypes1_21_9.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_6.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets1_21_6.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets1_21_6.PLAYER_ABILITIES);
registerGameEvent(ClientboundPackets1_21_6.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets1_21_6.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_6.RESPAWN);
registerTrackerWithData1_21_9(ClientboundPackets26_1.ADD_ENTITY, EntityTypes1_21_11.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets26_1.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets26_1.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets26_1.PLAYER_ABILITIES);
registerGameEvent(ClientboundPackets26_1.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets26_1.LOGIN);
registerRespawn1_20_5(ClientboundPackets26_1.RESPAWN);
}
@Override
protected void registerRewrites() {
final EntityDataTypes1_21_9 entityDataTypes = protocol.mappedTypes().entityDataTypes();
final EntityDataTypes26_1 entityDataTypes = protocol.mappedTypes().entityDataTypes();
filter().mapDataType(entityDataTypes::byId);
/* ... or something this if entity data classes changed
filter().mapDataType(typeId -> {
@@ -78,6 +78,6 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_9.getTypeFromId(type);
return EntityTypes1_21_11.getTypeFromId(type);
}
}
@@ -20,9 +20,9 @@ package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_5;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_11;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
@@ -30,12 +30,12 @@ import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.data.item.ItemHasherBase;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundConfigurationPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundConfigurationPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
@@ -47,65 +47,64 @@ import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_98To1_99, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99 - move the latter two to a rewriter package
// ClientboundPacket1_21_6
// ServerboundPacket1_21_6
// EntityTypes1_21_9 (MAPPED type)
// VersionedTypes.V1_21_9
// 1.99, 1.98
final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6, ClientboundPacket1_21_6, ServerboundPacket1_21_6, ServerboundPacket1_21_6> {
// ClientboundPacket26_1
// ServerboundPacket1_21_9
// EntityDataTypes26_1 (MAPPED type)
// VersionedTypes.V26_1
// 98.1, 99.1
final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket1_21_9> {
public static final MappingData MAPPINGS = new MappingDataBase("1.98", "1.99");
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
private final ParticleRewriter<ClientboundPacket1_21_6> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPacket1_21_6> tagRewriter = new TagRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket1_21_6> componentRewriter = new ComponentRewriter1_99(this);
public static final MappingData MAPPINGS = new MappingDataBase("98.1", "99.1");
private final EntityPacketRewriter99_1 entityRewriter = new EntityPacketRewriter99_1(this);
private final BlockItemPacketRewriter99_1 itemRewriter = new BlockItemPacketRewriter99_1(this);
private final ParticleRewriter<ClientboundPacket26_1> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPacket26_1> tagRewriter = new TagRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket26_1> componentRewriter = new ComponentRewriter99_1(this);
private final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(this);
public Protocol1_98To1_99() {
public Protocol98_1To99_1() {
// Passing the class types into the super constructor is needed for automatic packet type id remapping, but can otherwise be omitted
super(ClientboundPacket1_21_6.class, ClientboundPacket1_21_6.class, ServerboundPacket1_21_6.class, ServerboundPacket1_21_6.class);
super(ClientboundPacket26_1.class, ClientboundPacket26_1.class, ServerboundPacket1_21_9.class, ServerboundPacket1_21_9.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundConfigurationPackets1_21_6.REGISTRY_DATA, registryDataRewriter::handle);
registerClientbound(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.registerGeneric(ClientboundPackets1_21_6.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_6.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundPackets26_1.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_9.UPDATE_TAGS);
// If needed for item or component changes
componentRewriter.registerOpenScreen1_14(ClientboundPackets1_21_6.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets1_21_6.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.DISCONNECT);
componentRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_6.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets1_21_6.TAB_LIST);
componentRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets1_21_6.SET_PLAYER_TEAM);
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_6.PLAYER_COMBAT_KILL);
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_6.PLAYER_INFO_UPDATE);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SYSTEM_CHAT);
componentRewriter.registerDisguisedChat(ClientboundPackets1_21_6.DISGUISED_CHAT);
componentRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_6.PLAYER_CHAT);
componentRewriter.registerSetObjective(ClientboundPackets1_21_6.SET_OBJECTIVE);
componentRewriter.registerSetScore1_20_3(ClientboundPackets1_21_6.SET_SCORE);
componentRewriter.registerOpenScreen1_14(ClientboundPackets26_1.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets26_1.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.DISCONNECT);
componentRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_9.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets26_1.TAB_LIST);
componentRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets26_1.SET_PLAYER_TEAM);
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets26_1.PLAYER_COMBAT_KILL);
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets26_1.PLAYER_INFO_UPDATE);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SYSTEM_CHAT);
componentRewriter.registerDisguisedChat(ClientboundPackets26_1.DISGUISED_CHAT);
componentRewriter.registerPlayerChat1_21_5(ClientboundPackets26_1.PLAYER_CHAT);
componentRewriter.registerSetObjective(ClientboundPackets26_1.SET_OBJECTIVE);
componentRewriter.registerSetScore1_20_3(ClientboundPackets26_1.SET_SCORE);
componentRewriter.registerPing();
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_6.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_9(ClientboundPackets1_21_6.EXPLODE); // Rewrites the included sound and particles
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets26_1.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_9(ClientboundPackets26_1.EXPLODE); // Rewrites the included sound and particles
final SoundRewriter<ClientboundPacket1_21_6> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_6.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_6.SOUND_ENTITY);
final SoundRewriter<ClientboundPacket26_1> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets26_1.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets26_1.SOUND_ENTITY);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_6.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_6.UPDATE_ATTRIBUTES);
new StatisticsRewriter<>(this).register(ClientboundPackets26_1.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets26_1.UPDATE_ATTRIBUTES);
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
/*new CommandRewriter1_19_4<>(this) {
@@ -118,13 +117,13 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
super.handleArgument(wrapper, argumentType);
}
}
}.registerDeclareCommands1_19(ClientboundPackets1_21_6.COMMANDS);*/
}.registerDeclareCommands1_19(ClientboundPackets26_1.COMMANDS);*/
}
@Override
protected void onMappingDataLoaded() {
// Uncomment this if the entity types enum has been newly added specifically for this Protocol
// EntityTypes1_21_9.initialize(this);
// EntityTypes1_21_11.initialize(this);
// Uncomment if a new particle was added = ids shifted; requires a new Types_ class copied from the last
/*mappedTypes().particle.filler(this)
@@ -145,7 +144,7 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
.reader("effect", ParticleType.Readers.SPELL)
.reader("instant_effect", ParticleType.Readers.SPELL)
.reader("flash", ParticleType.Readers.COLOR)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));*/
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemTemplateType()));*/
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
}
@@ -153,7 +152,7 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
@Override
public void init(final UserConnection connection) {
// Register the entity tracker - used for entity id/entity data rewriting AND for tracking world data sent to the client (then used for chunk data rewriting)
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_9.PLAYER));
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
}
@@ -165,12 +164,12 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
}
@Override
public EntityPacketRewriter1_99 getEntityRewriter() {
public EntityPacketRewriter99_1 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter1_99 getItemRewriter() {
public BlockItemPacketRewriter99_1 getItemRewriter() {
return itemRewriter;
}
@@ -180,37 +179,37 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
}
@Override
public ParticleRewriter<ClientboundPacket1_21_6> getParticleRewriter() {
public ParticleRewriter<ClientboundPacket26_1> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21_6> getTagRewriter() {
public TagRewriter<ClientboundPacket26_1> getTagRewriter() {
return tagRewriter;
}
@Override
public NBTComponentRewriter<ClientboundPacket1_21_6> getComponentRewriter() {
public NBTComponentRewriter<ClientboundPacket26_1> getComponentRewriter() {
return componentRewriter;
}
@Override
public Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_9> types() {
return VersionedTypes.V1_21_9;
public Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes26_1> types() {
return VersionedTypes.V26_1;
}
@Override
public Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_9> mappedTypes() {
return VersionedTypes.V1_21_9;
public Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes26_1> mappedTypes() {
return VersionedTypes.V26_1;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21_6, ClientboundPacket1_21_6, ServerboundPacket1_21_6, ServerboundPacket1_21_6> createPacketTypesProvider() {
protected PacketTypesProvider<ClientboundPacket26_1, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket1_21_9> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_6.class, ClientboundConfigurationPackets1_21_6.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_6.class, ClientboundConfigurationPackets1_21_6.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_6.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_6.class)
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets26_1.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets26_1.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class)
);
}
}
@@ -67,10 +67,7 @@ public class ItemPacketRewriter1_11 extends ItemRewriter<ClientboundPackets1_9_3
if (enchTag != null && enchTag.isEmpty()) {
tag.putBoolean(nbtTagName("clearEnch"), true);
CompoundTag dummyTag = new CompoundTag();
dummyTag.putShort("id", Short.MAX_VALUE);
enchTag.add(dummyTag);
enchTag.add(new CompoundTag());
}
return item;
}
@@ -30,6 +30,7 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.ConnectionData;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.data.EntityIdMappings1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.data.ParticleIdMappings1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.BlockStorage;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
@@ -153,6 +154,7 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
ConnectionData.clearBlockStorage(wrapper.user());
}
tracker(wrapper.user()).clearEntities();
wrapper.user().get(BlockStorage.class).clear();
}
});
handler(Protocol1_12_2To1_13.SEND_DECLARE_COMMANDS_AND_TAGS);
@@ -302,13 +302,15 @@ public class WorldPacketRewriter1_13 {
protocol.registerClientbound(ClientboundPackets1_12_1.FORGET_LEVEL_CHUNK, new PacketHandlers() {
@Override
public void register() {
if (Via.getConfig().isServersideBlockConnections()) {
handler(wrapper -> {
int x = wrapper.passthrough(Types.INT);
int z = wrapper.passthrough(Types.INT);
handler(wrapper -> {
int x = wrapper.passthrough(Types.INT);
int z = wrapper.passthrough(Types.INT);
wrapper.user().get(BlockStorage.class).removeChunk(x, z);
if (Via.getConfig().isServersideBlockConnections()) {
ConnectionData.blockConnectionProvider.unloadChunk(wrapper.user(), x, z);
});
}
}
});
}
});
@@ -19,15 +19,15 @@ package com.viaversion.viaversion.protocols.v1_12_2to1_13.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.ChunkPosition;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.HashMap;
import java.util.Map;
// TODO Fix memory leak lolz (only a smol one tho)
public class BlockStorage implements StorableObject {
private static final IntSet WHITELIST = new IntOpenHashSet(46);
private final Map<BlockPosition, ReplacementData> blocks = new HashMap<>();
private final Map<Long, Map<BlockPosition, ReplacementData>> blocks = new HashMap<>();
static {
// Flower pots
@@ -62,7 +62,8 @@ public class BlockStorage implements StorableObject {
if (!WHITELIST.contains(block))
return;
blocks.put(position, new ReplacementData(block, replacementId));
final long chunkKey = ChunkPosition.chunkKeyForBlock(position.x(), position.z());
blocks.computeIfAbsent(chunkKey, key -> new HashMap<>()).put(position, new ReplacementData(block, replacementId));
}
public boolean isWelcome(int block) {
@@ -70,15 +71,35 @@ public class BlockStorage implements StorableObject {
}
public boolean contains(BlockPosition position) {
return blocks.containsKey(position);
final Map<BlockPosition, ReplacementData> chunkBlocks = blocks.get(ChunkPosition.chunkKeyForBlock(position.x(), position.z()));
return chunkBlocks != null && chunkBlocks.containsKey(position);
}
public ReplacementData get(BlockPosition position) {
return blocks.get(position);
final Map<BlockPosition, ReplacementData> chunkBlocks = blocks.get(ChunkPosition.chunkKeyForBlock(position.x(), position.z()));
return chunkBlocks != null ? chunkBlocks.get(position) : null;
}
public ReplacementData remove(BlockPosition position) {
return blocks.remove(position);
final long chunkKey = ChunkPosition.chunkKeyForBlock(position.x(), position.z());
final Map<BlockPosition, ReplacementData> chunkBlocks = blocks.get(chunkKey);
if (chunkBlocks == null) {
return null;
}
final ReplacementData removed = chunkBlocks.remove(position);
if (chunkBlocks.isEmpty()) {
blocks.remove(chunkKey);
}
return removed;
}
public void removeChunk(int chunkX, int chunkZ) {
blocks.remove(ChunkPosition.chunkKey(chunkX, chunkZ));
}
public void clear() {
blocks.clear();
}
public static final class ReplacementData {
@@ -23,17 +23,18 @@ import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.StringType;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ClientboundPackets1_17;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ServerboundPackets1_17;
import com.viaversion.viaversion.protocols.v1_17to1_17_1.packet.ClientboundPackets1_17_1;
import com.viaversion.viaversion.protocols.v1_17to1_17_1.rewriter.ItemPacketRewriter1_17_1;
public final class Protocol1_17To1_17_1 extends AbstractProtocol<ClientboundPackets1_17, ClientboundPackets1_17_1, ServerboundPackets1_17, ServerboundPackets1_17> {
private static final StringType PAGE_STRING_TYPE = new StringType(8192);
private static final StringType TITLE_STRING_TYPE = new StringType(128);
private final ItemPacketRewriter1_17_1 itemRewriter = new ItemPacketRewriter1_17_1(this);
public Protocol1_17To1_17_1() {
super(ClientboundPackets1_17.class, ClientboundPackets1_17_1.class, ServerboundPackets1_17.class, ServerboundPackets1_17.class);
@@ -41,43 +42,14 @@ public final class Protocol1_17To1_17_1 extends AbstractProtocol<ClientboundPack
@Override
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundPackets1_17.REMOVE_ENTITY, ClientboundPackets1_17_1.REMOVE_ENTITIES, wrapper -> {
// Aaaaand back to an array again!
int entityId = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, new int[]{entityId});
});
registerClientbound(ClientboundPackets1_17.CONTAINER_SET_SLOT, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE); // Container id
create(Types.VAR_INT, 0); // Add arbitrary state id
}
});
registerClientbound(ClientboundPackets1_17.CONTAINER_SET_CONTENT, new PacketHandlers() {
@Override
public void register() {
map(Types.UNSIGNED_BYTE); // Container id
create(Types.VAR_INT, 0); // Add arbitrary state id
handler(wrapper -> {
// Length encoded as var int now
wrapper.write(Types.ITEM1_13_2_ARRAY, wrapper.read(Types.ITEM1_13_2_SHORT_ARRAY));
// Carried item - should work like this
wrapper.write(Types.ITEM1_13_2, null);
});
}
});
registerServerbound(ServerboundPackets1_17.CONTAINER_CLICK, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE); // Container id
read(Types.VAR_INT); // Remove state id
}
});
registerServerbound(ServerboundPackets1_17.EDIT_BOOK, wrapper -> {
CompoundTag tag = new CompoundTag();
Item item = new DataItem(942, (byte) 1, tag); // Magic value for writable books
@@ -122,4 +94,9 @@ public final class Protocol1_17To1_17_1 extends AbstractProtocol<ClientboundPack
wrapper.write(Types.VAR_INT, slot);
});
}
@Override
public ItemPacketRewriter1_17_1 getItemRewriter() {
return itemRewriter;
}
}
@@ -0,0 +1,203 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_17to1_17_1.rewriter;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ClientboundPackets1_17;
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ServerboundPackets1_17;
import com.viaversion.viaversion.protocols.v1_17to1_17_1.Protocol1_17To1_17_1;
import com.viaversion.viaversion.rewriter.ItemRewriter;
import com.viaversion.viaversion.rewriter.RecipeRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Limit;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class ItemPacketRewriter1_17_1 extends ItemRewriter<ClientboundPackets1_17, ServerboundPackets1_17, Protocol1_17To1_17_1> {
public ItemPacketRewriter1_17_1(Protocol1_17To1_17_1 protocol) {
super(protocol, Types.ITEM1_13_2, Types.ITEM1_13_2_SHORT_ARRAY);
}
@Override
public void registerPackets() {
registerMerchantOffers(ClientboundPackets1_17.MERCHANT_OFFERS);
registerSetEquipment(ClientboundPackets1_17.SET_EQUIPMENT);
registerAdvancements(ClientboundPackets1_17.UPDATE_ADVANCEMENTS);
new RecipeRewriter<>(protocol).register(ClientboundPackets1_17.UPDATE_RECIPES);
registerSetCreativeModeSlot(ServerboundPackets1_17.SET_CREATIVE_MODE_SLOT);
protocol.registerClientbound(ClientboundPackets1_17.CONTAINER_SET_SLOT, wrapper -> {
wrapper.passthrough(Types.BYTE); // Container id
wrapper.write(Types.VAR_INT, 0); // Add arbitrary state id
wrapper.passthrough(Types.SHORT); // Slot id
passthroughClientboundItem(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_17.CONTAINER_SET_CONTENT, wrapper -> {
wrapper.passthrough(Types.UNSIGNED_BYTE); // Container id
wrapper.write(Types.VAR_INT, 0); // Add arbitrary state id
// Length encoded as var int now
Item[] items = wrapper.passthroughAndMap(Types.ITEM1_13_2_SHORT_ARRAY, Types.ITEM1_13_2_ARRAY);
for (int i = 0; i < items.length; i++) {
items[i] = handleItemToClient(wrapper.user(), items[i]);
}
// Carried item - should work like this
wrapper.write(Types.ITEM1_13_2, null);
});
protocol.registerServerbound(ServerboundPackets1_17.CONTAINER_CLICK, wrapper -> {
wrapper.passthrough(Types.BYTE); // Container id
wrapper.read(Types.VAR_INT); // Remove state id
wrapper.passthrough(Types.SHORT); // Slot
wrapper.passthrough(Types.BYTE); // Button
wrapper.passthrough(Types.VAR_INT); // Mode
// Affected items
final int length = Limit.max(wrapper.passthrough(Types.VAR_INT), 128);
for (int i = 0; i < length; i++) {
wrapper.passthrough(Types.SHORT); // Slot
wrapper.write(Types.ITEM1_13_2, handleItemToServer(wrapper.user(), wrapper.read(Types.ITEM1_13_2)));
}
// Carried item
wrapper.write(Types.ITEM1_13_2, handleItemToServer(wrapper.user(), wrapper.read(Types.ITEM1_13_2)));
});
}
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item == null) return null;
final CompoundTag tag = item.tag();
if (tag == null) {
return item;
}
int hideFlags = tag.getInt("HideFlags");
if ((hideFlags & 1) == 0) {
replaceInvalidEnchantments(tag, "Enchantments");
}
if ((hideFlags & 1 << 5) == 0) {
replaceInvalidEnchantments(tag, "StoredEnchantments");
}
return item;
}
@Override
public @Nullable Item handleItemToServer(final UserConnection connection, @Nullable final Item item) {
if (item == null) return null;
final CompoundTag tag = item.tag();
if (tag == null) {
return item;
}
restoreInvalidEnchantments(tag, "Enchantments");
restoreInvalidEnchantments(tag, "StoredEnchantments");
return item;
}
private void replaceInvalidEnchantments(CompoundTag tag, String tagName) {
final ListTag<CompoundTag> enchantments = tag.getListTag(tagName, CompoundTag.class);
if (enchantments == null) {
return;
}
// Check if any enchantment has an invalid level
boolean hasInvalidLevel = false;
for (final CompoundTag enchantment : enchantments.getValue()) {
final short lvl = enchantment.getShort("lvl");
if (lvl < 0 || lvl > 255) {
hasInvalidLevel = true;
break;
}
}
if (!hasInvalidLevel) {
return;
}
tag.put(nbtTagName(tagName), new ByteTag(true));
final int originalHideFlags = tag.getInt("HideFlags");
tag.put(nbtTagName("HideFlags"), new ByteTag((byte) originalHideFlags));
final int hideBit = tagName.equals("Enchantments") ? 1 : (1 << 5);
tag.put("HideFlags", new ByteTag((byte) (originalHideFlags | hideBit)));
CompoundTag display = tag.getCompoundTag("display");
if (display != null) {
tag.put(nbtTagName("display"), display.copy());
} else {
tag.put("display", display = new CompoundTag());
}
ListTag<StringTag> lore = display.getListTag("Lore", StringTag.class);
if (lore == null) {
display.put("Lore", lore = new ListTag<>(StringTag.class));
}
// Add all enchantments to lore in reverse order (so first enchantment ends up at top)
for (int i = enchantments.size() - 1; i >= 0; i--) {
final CompoundTag enchantment = enchantments.get(i);
final String id = enchantment.getString("id");
if (id == null) {
continue;
}
final short lvl = enchantment.getShort("lvl");
final Key key = Key.of(id);
lore.getValue().add(0, new StringTag("{\"italic\":false,\"color\":\"gray\",\"translate\":\"enchantment." + key.namespace() + "." + key.path() + "\",\"extra\":[\" \",{\"translate\":\"enchantment.level." + lvl + "\"}]}"));
}
}
private void restoreInvalidEnchantments(final CompoundTag tag, final String tagName) {
final Tag marker = tag.remove(nbtTagName(tagName));
if (marker == null) {
return;
}
final Tag hideFlags = tag.remove(nbtTagName("HideFlags"));
if (hideFlags != null) {
if (((ByteTag) hideFlags).asByte() == 0) {
tag.remove("HideFlags");
} else {
tag.put("HideFlags", hideFlags);
}
}
final Tag display = tag.remove(nbtTagName("display"));
if (display != null) {
tag.put("display", display);
} else {
tag.remove("display");
}
}
}
@@ -130,17 +130,6 @@ public final class Protocol1_19_1To1_19_3 extends AbstractProtocol<ClientboundPa
default -> super.handleArgument(wrapper, argumentType);
}
}
@Override
public String handleArgumentType(final String argumentType) {
return switch (argumentType) {
case "minecraft:resource" -> "minecraft:resource_key";
case "minecraft:resource_or_tag" -> "minecraft:resource_or_tag_key";
case "minecraft:entity_summon", "minecraft:item_enchantment", "minecraft:mob_effect" ->
"minecraft:resource";
default -> argumentType;
};
}
};
commandRewriter.registerDeclareCommands1_19(ClientboundPackets1_19_1.COMMANDS);
@@ -63,6 +63,11 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
final CompoundTag damageTypeRegistry = protocol.getMappingData().damageTypesRegistry();
registry.put("minecraft:damage_type", damageTypeRegistry);
final CompoundTag trimMaterialRegistry = new CompoundTag();
trimMaterialRegistry.putString("type", "minecraft:trim_material");
trimMaterialRegistry.put("value", new ListTag<>(CompoundTag.class));
registry.put("minecraft:trim_material", trimMaterialRegistry);
final ListTag<CompoundTag> biomes = TagUtil.getRegistryEntries(registry, "worldgen/biome");
for (final CompoundTag biomeTag : biomes) {
final CompoundTag biomeData = biomeTag.getCompoundTag("element");
@@ -102,7 +102,7 @@ public final class Protocol1_20_2To1_20_3 extends AbstractProtocol<ClientboundPa
wrapper.passthrough(Types.VAR_INT); // Score
// Null display and number format
wrapper.write(Types.OPTIONAL_TAG, null);
wrapper.write(Types.TRUSTED_OPTIONAL_TAG, null);
wrapper.write(Types.BOOLEAN, false);
});
registerClientbound(ClientboundPackets1_20_2.SET_OBJECTIVE, wrapper -> {
@@ -338,11 +338,11 @@ public final class Protocol1_20_2To1_20_3 extends AbstractProtocol<ClientboundPa
}
private void convertComponent(final PacketWrapper wrapper) {
wrapper.write(Types.TAG, ComponentUtil.jsonToTag(wrapper.read(Types.COMPONENT)));
wrapper.write(Types.TRUSTED_TAG, ComponentUtil.jsonToTag(wrapper.read(Types.COMPONENT)));
}
private void convertOptionalComponent(final PacketWrapper wrapper) {
wrapper.write(Types.OPTIONAL_TAG, ComponentUtil.jsonToTag(wrapper.read(Types.OPTIONAL_COMPONENT)));
wrapper.write(Types.TRUSTED_OPTIONAL_TAG, ComponentUtil.jsonToTag(wrapper.read(Types.OPTIONAL_COMPONENT)));
}
@Override
@@ -125,7 +125,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
});
registerClientbound(ClientboundPackets1_20_3.SERVER_DATA, wrapper -> {
wrapper.passthrough(Types.TAG); // MOTD
wrapper.passthrough(Types.TRUSTED_TAG); // MOTD
wrapper.passthrough(Types.OPTIONAL_BYTE_ARRAY_PRIMITIVE); // Icon
// Moved to join game
@@ -163,14 +163,14 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
return;
}
CompoundTag tag = wrapper.read(Types.COMPOUND_TAG);
CompoundTag tag = wrapper.read(Types.TRUSTED_COMPOUND_TAG);
if (tag != null) {
updateBlockEntityTag(wrapper.user(), null, tag);
} else {
// No longer nullable
tag = new CompoundTag();
}
wrapper.write(Types.COMPOUND_TAG, tag);
wrapper.write(Types.TRUSTED_COMPOUND_TAG, tag);
});
registerCooldown(ClientboundPackets1_20_3.COOLDOWN);
@@ -196,8 +196,8 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
// Display data
if (wrapper.passthrough(Types.BOOLEAN)) {
wrapper.passthrough(Types.TAG); // Title
wrapper.passthrough(Types.TAG); // Description
wrapper.passthrough(Types.TRUSTED_TAG); // Title
wrapper.passthrough(Types.TRUSTED_TAG); // Description
Item item = handleNonEmptyItemToClient(wrapper.user(), wrapper.read(itemType()));
wrapper.write(mappedItemType(), item);
@@ -827,11 +827,12 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
potionEffectToTag(effectTag, effect);
customEffects.add(effectTag);
}
tag.put("custom_effects", customEffects);
if (!customEffects.isEmpty()) {
tag.put("custom_effects", customEffects);
}
if (value.customName() != null) {
tag.putString("custom_name", value.customName());
}
tag.put("custom_effects", customEffects);
return tag;
}
@@ -425,7 +425,9 @@ public final class StructuredDataConverter {
customPotionEffectsTag.add(effectTag);
}
tag.put("custom_potion_effects", customPotionEffectsTag);
if (!customPotionEffectsTag.isEmpty()) {
tag.put("custom_potion_effects", customPotionEffectsTag);
}
});
register(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, (data, tag) -> {
final ListTag<CompoundTag> effectsTag = new ListTag<>(CompoundTag.class);
@@ -99,7 +99,7 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
particleRewriter.registerExplode1_20_5(ClientboundPackets1_20_5.EXPLODE); // Rewrites the included sound and particles
registerClientbound(ClientboundPackets1_20_5.DISGUISED_CHAT, wrapper -> {
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TAG)); // Message
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TRUSTED_TAG)); // Message
// Holder time
final int chatType = wrapper.read(Types.VAR_INT);
@@ -121,7 +121,7 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
}
}
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.OPTIONAL_TAG)); // Unsigned content
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TRUSTED_OPTIONAL_TAG)); // Unsigned content
final int filterMaskType = wrapper.passthrough(Types.VAR_INT);
if (filterMaskType == 2) {
@@ -130,8 +130,8 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
final int chatType = wrapper.read(Types.VAR_INT);
wrapper.write(ChatType.TYPE, Holder.of(chatType));
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TAG)); // Name
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.OPTIONAL_TAG)); // Target Name
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TRUSTED_TAG)); // Name
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TRUSTED_OPTIONAL_TAG)); // Target Name
});
registerClientbound(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES, wrapper -> {
@@ -25,6 +25,8 @@ import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.TagData;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_4;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.Direction;
@@ -57,6 +59,8 @@ import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -344,15 +348,24 @@ public final class Protocol1_20To1_20_2 extends AbstractProtocol<ClientboundPack
// The client includes vanilla as the default feature when initially leaving the login phase
final LastTags lastTags = connection.get(LastTags.class);
boolean sentTags = false;
if (lastTags != null) {
if (lastTags.sentDuringConfigPhase()) {
lastTags.setSentDuringConfigPhase(false);
sentTags = true;
} else {
// The server might still follow up with a tags packet, but we wouldn't know
lastTags.sendLastTags(connection);
sentTags = lastTags.sendLastTags(connection);
}
}
if (!sentTags) {
// Send an empty tags packet to allow adding to it in later protocols
final PacketWrapper packet = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, connection);
packet.write(Types.VAR_INT, 0);
packet.send(Protocol1_20To1_20_2.class);
}
if (lastResourcePack != null && connection.getProtocolInfo().protocolVersion() == ProtocolVersion.v1_20_2) {
// The client for some reason drops the resource pack when reentering the configuration state
final PacketWrapper resourcePackPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK, connection);
@@ -90,7 +90,7 @@ public final class BlockItemPacketRewriter1_20_2 extends ItemRewriter<Clientboun
protocol.registerClientbound(ClientboundPackets1_19_4.BLOCK_ENTITY_DATA, wrapper -> {
wrapper.passthrough(Types.BLOCK_POSITION1_14); // Position
wrapper.passthrough(Types.VAR_INT); // Type
wrapper.write(Types.COMPOUND_TAG, handleBlockEntity(wrapper.read(Types.NAMED_COMPOUND_TAG)));
wrapper.write(Types.TRUSTED_COMPOUND_TAG, handleBlockEntity(wrapper.read(Types.NAMED_COMPOUND_TAG)));
});
protocol.registerClientbound(ClientboundPackets1_19_4.LEVEL_CHUNK_WITH_LIGHT, wrapper -> {
@@ -48,9 +48,9 @@ public class LastTags implements StorableObject {
}
}
public void sendLastTags(final UserConnection connection) {
public boolean sendLastTags(final UserConnection connection) {
if (registryTags.isEmpty()) {
return;
return false;
}
final PacketWrapper packet = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, connection);
@@ -64,6 +64,7 @@ public class LastTags implements StorableObject {
}
}
packet.send(Protocol1_20To1_20_2.class);
return true;
}
public void setSentDuringConfigPhase(final boolean sentDuringConfigPhase) {
Loaded 100 of 162 files, more files were not shown because too many files have changed in this diff. Show more