Compare commits

..
79 Commits
Author SHA1 Message Date
Nassim Jahnke c45c700301 Fix 1.21 player chat read type 2026-04-02 16:13:39 +02:00
Nassim Jahnke c43de2b88d Move 26.1 container empty item handling into proper upgrade/downgrade methods 2026-04-02 15:10:19 +02:00
Drex 898b6c8774 Improve enchantment term conversion (#4879) 2026-04-02 14:32:48 +02:00
Florian Reuth 2e3c47d292 Track sneaking state for secondary action in 1.21.11->26.1 (#4890) 2026-04-02 13:23:16 +02:00
Florian Reuth 7974d1a570 [ci skip] Update missing year references (#4786) 2026-04-02 11:56:51 +02:00
Florian Reuth cf2c1c5b76 Update time command translations in 1.21.11->26.1 (#4891) 2026-04-02 11:47:55 +02:00
Florian Reuth d75c54cc70 Fix kick when opening "edit game rules" screen (#4882) 2026-04-02 11:44:50 +02:00
Florian Reuth ead13b2bb9 Deprecate packet register methods with override boolean (#4881)
Replaced by Protocol#registerClientbound & Protocol#registerServerbound
2026-04-01 17:24:33 +02:00
Nassim Jahnke 2e91b841b0 Automatically call mapTypes in entity rewriter 2026-04-01 17:21:53 +02:00
Nassim Jahnke 50486fa43a Don't apply shared registrations to differing version types 2026-04-01 17:05:07 +02:00
Nassim Jahnke 31d4cd453d Add 26.1.1 to version string 2026-04-01 13:02:29 +02:00
Nassim Jahnke c5482b99bf [ci skip] Update error message 2026-03-31 21:15:01 +02:00
Nassim Jahnke 98ef806887 Fix baby wolf assets 2026-03-31 15:21:48 +02:00
Florian Reuth a26745862f Handle show_dialog click events (#4878) 2026-03-31 14:36:09 +02:00
Florian ReuthandNassim Jahnke 6bd081cefd Handle in-depth components in dialogs (#4876)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-03-31 11:25:47 +02:00
Nassim Jahnke bb9aa8b31c Fix adventure mode predicate index check in 1.20.4->1.20.5 2026-03-31 11:07:01 +02:00
Nassim Jahnke 572f7a2677 Fix hashing of attribute_modifiers with override text 2026-03-30 23:29:20 +02:00
Nassim Jahnke 11a5c9e32c Fix block entity tag read type 2026-03-30 23:09:37 +02:00
Nassim Jahnke 02b65dcb36 Fix command rewriter check being too early 2026-03-30 22:32:08 +02:00
Nassim Jahnke 0121534e7e Deduplicate particle type fillers 2026-03-30 21:53:47 +02:00
Florian Reuth 941e6f6df4 Null check block entity tag in 1.20->1.20.2 (#4872) 2026-03-30 20:40:26 +02:00
Nassim Jahnke fe6e18845b Make tests fail if error occurs during platform 2026-03-30 20:40:26 +02:00
Nassim Jahnke 8f8f5e72c0 Default rewriter registrations across protocols
In total it doesn't (yet) reduce the lines of code (though there is also some other changes adding code here), but makes adding single rewriter calls to a range of protocols much easier than having to individually check an ever increasing number of classes. This also moved Protocol#registerPackets until after mappings have been loaded (which makes onMappingDataLoaded redundant for now, but will become relevant later again)
2026-03-30 20:40:25 +02:00
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
237 changed files with 5409 additions and 2135 deletions

No files matched your search

+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
--------
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
* 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
@@ -0,0 +1,123 @@
/*
* 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.data;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import com.viaversion.viaversion.util.Key;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import org.checkerframework.checker.nullness.qual.Nullable;
public class FullIdentityMappings implements FullMappings {
private static final String[] EMPTY_ARRAY = new String[0];
private final Object2IntMap<String> stringToId;
private final String[] idToString;
private final Mappings mappings;
public FullIdentityMappings(final IdentifiersPair identifiersPair, final Mappings mappings) {
Preconditions.checkNotNull(mappings, "Mappings cannot be null");
this.mappings = mappings;
this.stringToId = FullMappingsBase.toInverseMap(identifiersPair.unmapped());
this.idToString = identifiersPair.unmapped().toArray(EMPTY_ARRAY);
}
private FullIdentityMappings(final Object2IntMap<String> stringToId, final String[] idToString, final Mappings mappings) {
this.stringToId = stringToId;
this.idToString = idToString;
this.mappings = mappings;
}
@Override
public int id(final String identifier) {
return stringToId.getInt(Key.stripMinecraftNamespace(identifier));
}
@Override
public int mappedId(final String mappedIdentifier) {
return id(mappedIdentifier);
}
@Override
public String identifier(final int id) {
if (id < 0 || id >= idToString.length) {
return null;
}
final String identifier = idToString[id];
return Key.namespaced(identifier);
}
@Override
public @Nullable String identifier(final String mappedIdentifier) {
final int mappedId = mappedId(mappedIdentifier);
if (mappedId == -1) {
return null;
}
final int id = mappings.inverse().getNewId(mappedId);
return id != -1 ? identifier(id) : null;
}
@Override
public @Nullable String mappedIdentifier(final int mappedId) {
return identifier(mappedId);
}
@Override
public @Nullable String mappedIdentifier(final String identifier) {
return identifier(identifier);
}
@Override
public int getNewId(int id) {
return mappings.getNewId(id);
}
@Override
public void setNewId(int id, int mappedId) {
mappings.setNewId(id, mappedId);
}
@Override
public int size() {
return mappings.size();
}
@Override
public int mappedSize() {
return mappings.mappedSize();
}
@Override
public boolean isIdentity() {
return true;
}
@Override
public boolean isIntIdIdentity() {
return true;
}
@Override
public FullMappings inverse() {
return new FullIdentityMappings(stringToId, idToString, mappings.inverse());
}
}
@@ -77,6 +77,14 @@ public interface FullMappings extends BiMappings {
*/
@Nullable String mappedIdentifier(String identifier);
/**
* Returns whether the int id mappings are identity mappings.
*
* @return whether the int id mappings are identity mappings
* @see #isIdentity()
*/
boolean isIntIdIdentity();
@Override
FullMappings inverse();
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.data;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import com.viaversion.viaversion.util.Key;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
@@ -37,13 +38,13 @@ public class FullMappingsBase implements FullMappings {
private final String[] mappedIdToString;
private final Mappings mappings;
public FullMappingsBase(final List<String> unmappedIdentifiers, final List<String> mappedIdentifiers, final Mappings mappings) {
public FullMappingsBase(final IdentifiersPair identifiersPair, final Mappings mappings) {
Preconditions.checkNotNull(mappings, "Mappings cannot be null");
this.mappings = mappings;
this.stringToId = toInverseMap(unmappedIdentifiers);
this.mappedStringToId = toInverseMap(mappedIdentifiers);
this.idToString = unmappedIdentifiers.toArray(EMPTY_ARRAY);
this.mappedIdToString = mappedIdentifiers.toArray(EMPTY_ARRAY);
this.stringToId = toInverseMap(identifiersPair.unmapped());
this.idToString = identifiersPair.unmapped().toArray(EMPTY_ARRAY);
this.mappedStringToId = toInverseMap(identifiersPair.mapped());
this.mappedIdToString = identifiersPair.mapped().toArray(EMPTY_ARRAY);
}
private FullMappingsBase(final Object2IntMap<String> stringToId, final Object2IntMap<String> mappedStringToId, final String[] idToString, final String[] mappedIdToString, final Mappings mappings) {
@@ -54,7 +55,11 @@ public class FullMappingsBase implements FullMappings {
this.mappings = mappings;
}
private static Object2IntMap<String> toInverseMap(final List<String> list) {
public static FullMappings of(final IdentifiersPair identifiersPair, final Mappings mappings) {
return mappings.isIdentity() && identifiersPair.identity() ? new FullIdentityMappings(identifiersPair, mappings) : new FullMappingsBase(identifiersPair, mappings);
}
static Object2IntMap<String> toInverseMap(final List<String> list) {
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(list.size());
map.defaultReturnValue(-1);
for (int i = 0; i < list.size(); i++) {
@@ -135,6 +140,11 @@ public class FullMappingsBase implements FullMappings {
return mappings.mappedSize();
}
@Override
public boolean isIntIdIdentity() {
return mappings.isIdentity();
}
@Override
public FullMappings inverse() {
return new FullMappingsBase(mappedStringToId, stringToId, mappedIdToString, idToString, mappings.inverse());
@@ -38,4 +38,9 @@ public record IdentityMappings(int size, int mappedSize) implements Mappings {
public Mappings inverse() {
return new IdentityMappings(mappedSize, size);
}
@Override
public boolean isIdentity() {
return true;
}
}
@@ -170,6 +170,8 @@ public interface MappingData {
@Nullable FullMappings getRecipeSerializerMappings();
@Nullable FullMappings getSlotDisplayMappings();
@Nullable FullMappings getDataComponentSerializerMappings();
default @Nullable FullMappings getFullMappings(final MappingType mappingType) {
@@ -26,6 +26,7 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.TagData;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
@@ -45,6 +46,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,19 +91,19 @@ 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");
blockEntityMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "blockentities");
final List<String> unmappedParticles = identifiersFromGlobalIds(unmappedIdentifierData, "particles");
final List<String> mappedParticles = identifiersFromGlobalIds(mappedIdentifierData, "particles");
if (unmappedParticles != null && mappedParticles != null) {
final IdentifiersPair particleIdentifiers = identifiersFromGlobalIds(unmappedIdentifierData, mappedIdentifierData, "particles");
if (particleIdentifiers != null) {
Mappings particleMappings = loadMappings(data, "particles");
if (particleMappings == null) {
particleMappings = new IdentityMappings(unmappedParticles.size(), mappedParticles.size());
particleMappings = new IdentityMappings(particleIdentifiers.unmapped().size(), particleIdentifiers.mapped().size());
}
this.particleMappings = new ParticleMappings(unmappedParticles, mappedParticles, particleMappings);
this.particleMappings = new ParticleMappings(particleIdentifiers, particleMappings);
}
} else {
// Might not have identifiers in older versions
@@ -130,6 +132,10 @@ public class MappingDataBase implements MappingData {
return MappingDataLoader.INSTANCE.identifiersFromGlobalIds(mappingsTag, key);
}
protected @Nullable IdentifiersPair identifiersFromGlobalIds(final CompoundTag unmappedTag, final CompoundTag mappedTag, final String key) {
return MappingDataLoader.INSTANCE.identifiersFromGlobalIds(unmappedTag, mappedTag, key);
}
protected @Nullable CompoundTag readMappingsFile(final String name) {
return MappingDataLoader.INSTANCE.loadNBT(name);
}
@@ -156,14 +162,12 @@ public class MappingDataBase implements MappingData {
return null;
}
final List<String> unmappedIdentifiers = identifiersFromGlobalIds(unmappedIdentifiersTag, key);
final List<String> mappedIdentifiers = identifiersFromGlobalIds(mappedIdentifiersTag, key);
final IdentifiersPair identifiersPair = identifiersFromGlobalIds(unmappedIdentifiersTag, mappedIdentifiersTag, key);
Mappings mappings = loadBiMappings(data, key); // Load as bi-mappings to keep the inverse cached
if (mappings == null) {
mappings = new IdentityMappings(unmappedIdentifiers.size(), mappedIdentifiers.size());
mappings = new IdentityMappings(identifiersPair.unmapped().size(), identifiersPair.mapped().size());
}
return new FullMappingsBase(unmappedIdentifiers, mappedIdentifiers, mappings);
return FullMappingsBase.of(identifiersPair, mappings);
}
protected @Nullable BiMappings loadBiMappings(final CompoundTag data, final String key) {
@@ -335,6 +339,11 @@ public class MappingDataBase implements MappingData {
return recipeSerializerMappings;
}
@Override
public @Nullable FullMappings getSlotDisplayMappings() {
return slotDisplayMappings;
}
@Override
public @Nullable IntSet changedBlocks() {
return changedBlocks;
@@ -81,8 +81,9 @@ public class MappingDataLoader {
for (final Map.Entry<String, Tag> entry : globalIdentifiers.entrySet()) {
//noinspection unchecked
final ListTag<StringTag> value = (ListTag<StringTag>) entry.getValue();
final String[] array = new String[value.size()];
for (int i = 0, size = value.size(); i < size; i++) {
final int size = value.size();
final String[] array = new String[size];
for (int i = 0; i < size; i++) {
array[i] = value.get(i).getValue();
}
GLOBAL_IDENTIFIER_INDEXES.put(entry.getKey(), array);
@@ -272,13 +273,60 @@ public class MappingDataLoader {
public @Nullable List<String> identifiersFromGlobalIds(final CompoundTag mappingsTag, final String key) {
final Mappings mappings = loadMappings(mappingsTag, key);
if (mappings == null) {
return mappings != null ? identifiers(mappings, key) : null;
}
/**
* Returns a pair of identifier lists, also keeping track of whether the two lists are equal.
*
* @param unmappedTag unmapped mappings tag
* @param mappedTag mapped mappings tag
* @param key mappings key
* @return pair of identifier lists
*/
public @Nullable IdentifiersPair identifiersFromGlobalIds(final CompoundTag unmappedTag, final CompoundTag mappedTag, final String key) {
final Mappings unmapped = loadMappings(unmappedTag, key);
if (unmapped == null) {
return null;
}
final Mappings mapped = loadMappings(mappedTag, key);
if (mapped == null) {
return null;
}
final int size = unmapped.size();
if (size != mapped.size()) {
return new IdentifiersPair(identifiers(unmapped, key), identifiers(mapped, key), false);
}
// Small optimization to only load one array and reduce loading for full mappings
final List<String> unmappedIdentifiers = new ArrayList<>(size);
final List<String> mappedIdentifiers = new ArrayList<>(size);
boolean identity = true;
for (int i = 0; i < size; i++) {
final int unmappedGlobalId = unmapped.getNewId(i);
final int mappedGlobalId = mapped.getNewId(i);
final String unmappedIdentifier = identifierFromGlobalId(key, unmappedGlobalId);
if (unmappedGlobalId == mappedGlobalId) {
unmappedIdentifiers.add(unmappedIdentifier);
mappedIdentifiers.add(unmappedIdentifier);
continue;
}
identity = false;
unmappedIdentifiers.add(unmappedIdentifier);
mappedIdentifiers.add(identifierFromGlobalId(key, mappedGlobalId));
}
return identity ? new IdentifiersPair(unmappedIdentifiers) : new IdentifiersPair(unmappedIdentifiers, mappedIdentifiers);
}
private List<String> identifiers(final Mappings mappings, final String key) {
final List<String> identifiers = new ArrayList<>(mappings.size());
for (int i = 0; i < mappings.size(); i++) {
identifiers.add(identifierFromGlobalId(key, mappings.getNewId(i)));
final int globalId = mappings.getNewId(i);
identifiers.add(identifierFromGlobalId(key, globalId));
}
return identifiers;
}
@@ -342,4 +390,15 @@ public class MappingDataLoader {
T create(V mappings, int mappedSize);
}
public record IdentifiersPair(List<String> unmapped, List<String> mapped, boolean identity) {
public IdentifiersPair(final List<String> unmapped, final List<String> mapped) {
this(unmapped, mapped, false);
}
public IdentifiersPair(final List<String> identifiers) {
this(identifiers, identifiers, true);
}
}
}
@@ -22,6 +22,8 @@
*/
package com.viaversion.viaversion.api.data;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface Mappings {
/**
@@ -84,4 +86,40 @@ public interface Mappings {
* @return mappings with keys and values swapped
*/
Mappings inverse();
/**
* Returns whether the mappings are unchanged identity mappings.
*
* @return whether the mappings are unchanged identity mappings
*/
default boolean isIdentity() {
return false;
}
/**
* Returns whether the mappings null or identity mappings.
*
* @param mappings mappings
* @return whether the mappings are identity mappings
* @see #isFullIdentity(Mappings)
*/
static boolean isIntIdIdentity(@Nullable final Mappings mappings) {
if (mappings == null) {
return true;
}
return mappings instanceof FullMappings fullMappings ? fullMappings.isIntIdIdentity() : mappings.isIdentity();
}
/**
* Returns whether the mappings null or full identity mappings.
* Stronger than {@link #isIntIdIdentity(Mappings)}, but equal to that if not {@link FullMappings}.
*
* @param mappings mappings
* @return whether the mappings are full identity mappings
* @see #isIntIdIdentity(Mappings)
*/
static boolean isFullIdentity(@Nullable final Mappings mappings) {
return mappings == null || mappings.isIdentity();
}
}
@@ -22,16 +22,16 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
public class ParticleMappings extends FullMappingsBase {
private final IntList itemParticleIds = new IntArrayList(4);
private final IntList blockParticleIds = new IntArrayList(4);
public ParticleMappings(final List<String> unmappedIdentifiers, final List<String> mappedIdentifiers, final Mappings mappings) {
super(unmappedIdentifiers, mappedIdentifiers, mappings);
public ParticleMappings(final IdentifiersPair identifiersPair, final Mappings mappings) {
super(identifiersPair, mappings);
addBlockParticle("block");
addBlockParticle("falling_dust");
addBlockParticle("block_marker");
@@ -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);
}
@@ -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;
@@ -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());
}
}
@@ -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);
@@ -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)
@@ -37,6 +37,7 @@ import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) implements Copyable, Rewritable {
@@ -226,7 +227,7 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
}
public static class Display implements Copyable {
public static final String[] DISPLAY_TYPES = {"default", "hidden", "override_text"};
public static final String[] DISPLAY_TYPES = {"default", "hidden", "override"};
public static final Display DEFAULT = new Display(0);
private final int id;
@@ -246,6 +247,17 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
public Display copy() {
return this;
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof final Display display)) return false;
return id == display.id;
}
@Override
public int hashCode() {
return id;
}
}
public static final class OverrideText extends Display {
@@ -271,5 +283,19 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
public OverrideText copy() {
return new OverrideText(this.component.copy());
}
@Override
public boolean equals(final Object o) {
if (!(o instanceof final OverrideText that)) return false;
if (!super.equals(o)) return false;
return Objects.equals(component, that.component);
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + Objects.hashCode(component);
return result;
}
}
}
@@ -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) {
@@ -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);
}
@@ -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);
}
@@ -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#sendServerDetails()} 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.
*
@@ -68,10 +68,6 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
registerServerbound(state, packetType.getId(), packetType.getId(), handler, false);
}
default void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
registerServerbound(state, unmappedPacketId, mappedPacketId, handler, false);
}
/**
* Registers a serverbound packet, with id transformation and remapper.
*
@@ -79,19 +75,17 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
* @param unmappedPacketId unmapped packet id
* @param mappedPacketId mapped packet id
* @param handler packet handler
* @param override whether an existing mapper should be overridden
* @see #registerServerbound(ServerboundPacketType, ServerboundPacketType, PacketHandler, boolean)
*/
default void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
registerServerbound(state, unmappedPacketId, mappedPacketId, handler, false);
}
@Deprecated(forRemoval = true)
void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler, boolean override);
void cancelServerbound(State state, int mappedPacketId);
default void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
registerClientbound(state, unmappedPacketId, mappedPacketId, handler, false);
}
void cancelClientbound(State state, int unmappedPacketId);
/**
* Registers a clientbound packet, with id transformation and remapper.
*
@@ -99,9 +93,15 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
* @param unmappedPacketId unmapped packet id
* @param mappedPacketId mapped packet id
* @param handler packet handler
* @param override whether an existing mapper should be overridden
* @see #registerClientbound(ClientboundPacketType, ClientboundPacketType, PacketHandler, boolean)
*/
default void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
registerClientbound(state, unmappedPacketId, mappedPacketId, handler, false);
}
void cancelClientbound(State state, int unmappedPacketId);
@Deprecated(forRemoval = true)
void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler, boolean override);
// ---------------------------------------------------------------------------------------
@@ -144,6 +144,7 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
* @param handler packet handler
* @param override whether an existing mapping should be overridden if present
*/
@Deprecated(forRemoval = true)
void registerClientbound(CU packetType, @Nullable CM mappedPacketType, @Nullable PacketHandler handler, boolean override);
/**
@@ -191,6 +192,7 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
* @param handler packet handler
* @param override whether an existing mapping should be overridden if present
*/
@Deprecated(forRemoval = true)
void registerServerbound(SU packetType, @Nullable SM mappedPacketType, @Nullable PacketHandler handler, boolean override);
/**
@@ -260,6 +262,22 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
*/
void appendServerbound(SU type, PacketHandler handler);
/**
* Replaces a clientbound packet type handler with another.
*
* @param type clientbound packet type
* @param handler packet handler
*/
void replaceClientbound(CU type, @Nullable PacketHandler handler);
/**
* Replaces a serverbound packet type handler with another.
*
* @param type serverbound packet type
* @param handler packet handler
*/
void replaceServerbound(SU type, @Nullable PacketHandler handler);
/**
* Transform a packet using this protocol
*
@@ -441,4 +459,13 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
default boolean isBaseProtocol() {
return false;
}
/**
* Marks this protocol as dependent on another. Before being initialized, it will wait for the dependency's completion.
*
* @return protocol class to depend on
*/
default @Nullable Class<? extends Protocol<?, ?, ?, ?>> dependsOn() {
return null;
}
}
@@ -249,7 +249,17 @@ public interface ProtocolManager {
*
* @return true if the executor has now been shut down
*/
boolean checkForMappingCompletion();
default boolean checkForMappingCompletion() {
return checkForMappingCompletion(false);
}
/**
* Shuts down the executor and uncaches mappings if all futures have been completed.
*
* @param propagateErrors whether to propagate errors from the futures to the caller
* @return true if the executor has now been shut down
*/
boolean checkForMappingCompletion(boolean propagateErrors);
/**
* Executes the given runnable asynchronously, adding a {@link CompletableFuture}
@@ -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)}.
@@ -50,6 +50,11 @@ final class PacketIdMapping implements PacketMapping {
}
}
@Override
public void setHandler(@Nullable final PacketHandler handler) {
this.handler = handler;
}
@Override
public @Nullable PacketHandler handler() {
return handler;
@@ -39,6 +39,13 @@ public interface PacketMapping {
*/
void applyType(PacketWrapper wrapper);
/**
* Replaces the current packet handler.
*
* @param handler packet transformer
*/
void setHandler(@Nullable PacketHandler handler);
/**
* Returns a packet transformer to transform a packet from one protocol version to another.
*
@@ -52,6 +52,11 @@ final class PacketTypeMapping implements PacketMapping {
}
}
@Override
public void setHandler(@Nullable final PacketHandler handler) {
this.handler = handler;
}
@Override
public @Nullable PacketHandler handler() {
return handler;
@@ -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-26.1.1", new SubVersionRange("26.1", 0, 1));
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -26,6 +26,7 @@ import com.google.gson.JsonElement;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface ComponentRewriter {
@@ -37,4 +38,6 @@ public interface ComponentRewriter {
JsonElement processText(UserConnection connection, @Nullable String json);
void handleShowItem(UserConnection connection, CompoundTag itemTag);
void passthroughAndProcess(PacketWrapper wrapper);
}
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.protocol.Protocol;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter<T> {
@@ -39,6 +40,11 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
*/
EntityType typeFromId(int type);
default @Nullable EntityType typeFromId(final String type) {
final int id = protocol().getMappingData().getEntityMappings().id(type);
return id == -1 ? null : typeFromId(id);
}
/**
* Returns the entity type from the given id.
* From 1.14 and onwards, this is the same exact value as {@link #typeFromId(int)}.
@@ -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,22 @@
*/
package com.viaversion.viaversion.api.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
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);
void handle(PacketWrapper wrapper);
@Nullable
KeyMappings getMappings(String registryKey);
boolean shouldRemoveRegistry(String registryKey);
boolean hasRegistriesToRemove();
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;
@@ -198,13 +199,16 @@ 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 = 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);
@@ -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;
}
@@ -20,17 +20,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.protocol;
package com.viaversion.viaversion.api.type.types.chunk;
/**
* A simple protocol which does not have any packet types.
* <p>
* {@link AbstractProtocol} should be preferred over this class in most cases.
*/
public abstract class AbstractSimpleProtocol extends AbstractProtocol<SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes,
SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes> implements SimpleProtocol {
public final class ChunkType26_1 extends ChunkType1_21_5 {
protected AbstractSimpleProtocol() {
super(null, null, null, null);
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);
}
}
@@ -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
@@ -59,17 +59,13 @@ public class ParticleType extends DynamicType<Particle> {
return protocol.getMappingData().getParticleMappings();
}
public static DataReader<Particle> itemHandler(final Type<Item> itemType) {
return (buf, particle) -> particle.add(itemType, itemType.read(buf));
}
public static final class Readers {
public static final DataReader<Particle> BLOCK = (buf, particle) -> {
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Flat Block
};
public static final DataReader<Particle> ITEM1_13 = itemHandler(Types.ITEM1_13);
public static final DataReader<Particle> ITEM1_13_2 = itemHandler(Types.ITEM1_13_2);
public static final DataReader<Particle> ITEM1_13 = item(Types.ITEM1_13);
public static final DataReader<Particle> ITEM1_13_2 = item(Types.ITEM1_13_2);
public static final DataReader<Particle> DUST = (buf, particle) -> {
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Red 0-1
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Green 0-1
@@ -172,4 +168,103 @@ public class ParticleType extends DynamicType<Particle> {
return (buf, particle) -> particle.add(item, item.read(buf));
}
}
public static final class Fillers {
public static DynamicType<Particle>.DataFiller fill1_13_2(final Protocol<?, ?, ?, ?> protocol, final ParticleType type, final boolean useMappedNames) {
return type.filler(protocol, useMappedNames)
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
.reader("block", Readers.BLOCK)
.reader("dust", Readers.DUST)
.reader("falling_dust", Readers.BLOCK);
}
public static DataFiller fill1_17(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
return fill1_13_2(protocol, type, true)
.reader("dust_color_transition", Readers.DUST_TRANSITION)
.reader("vibration", Readers.VIBRATION);
}
public static void fill1_18(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
fill1_17(protocol, type).reader("block_marker", Readers.BLOCK);
}
public static void fill1_19(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
type.filler(protocol)
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
.reader("block", Readers.BLOCK)
.reader("block_marker", Readers.BLOCK)
.reader("dust", Readers.DUST)
.reader("falling_dust", Readers.BLOCK)
.reader("dust_color_transition", Readers.DUST_TRANSITION)
.reader("vibration", Readers.VIBRATION1_19)
.reader("sculk_charge", Readers.SCULK_CHARGE)
.reader("shriek", Readers.SHRIEK);
}
public static DataFiller fill1_20_3(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
return type.filler(protocol)
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
.reader("block", Readers.BLOCK)
.reader("block_marker", Readers.BLOCK)
.reader("dust", Readers.DUST)
.reader("falling_dust", Readers.BLOCK)
.reader("dust_color_transition", Readers.DUST_TRANSITION)
.reader("vibration", Readers.VIBRATION1_20_3)
.reader("sculk_charge", Readers.SCULK_CHARGE)
.reader("shriek", Readers.SHRIEK);
}
public static void fill1_20_5(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
fill1_20_3(protocol, type)
.reader("dust_pillar", Readers.BLOCK)
.reader("entity_effect", Readers.COLOR);
}
public static void fill1_21_2(final Protocol<?, ?, ?, ?> protocol) {
protocol.mappedTypes().particle().filler(protocol)
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
.reader("block", Readers.BLOCK)
.reader("block_marker", Readers.BLOCK)
.reader("dust_pillar", Readers.BLOCK)
.reader("falling_dust", Readers.BLOCK)
.reader("block_crumble", Readers.BLOCK)
.reader("dust", Readers.DUST1_21_2)
.reader("dust_color_transition", Readers.DUST_TRANSITION1_21_2)
.reader("vibration", Readers.VIBRATION1_20_3)
.reader("sculk_charge", Readers.SCULK_CHARGE)
.reader("shriek", Readers.SHRIEK)
.reader("entity_effect", Readers.COLOR)
.reader("trail", Readers.TRAIL1_21_2);
}
public static DataFiller fill1_21_4(final Protocol<?, ?, ?, ?> protocol) {
return protocol.mappedTypes().particle().filler(protocol)
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemTemplateType()))
.reader("block", Readers.BLOCK)
.reader("block_marker", Readers.BLOCK)
.reader("dust_pillar", Readers.BLOCK)
.reader("falling_dust", Readers.BLOCK)
.reader("block_crumble", Readers.BLOCK)
.reader("dust", Readers.DUST1_21_2)
.reader("dust_color_transition", Readers.DUST_TRANSITION1_21_2)
.reader("vibration", Readers.VIBRATION1_20_3)
.reader("sculk_charge", Readers.SCULK_CHARGE)
.reader("shriek", Readers.SHRIEK)
.reader("entity_effect", Readers.COLOR)
.reader("trail", Readers.TRAIL1_21_4);
}
public static DataFiller fill1_21_5(final Protocol<?, ?, ?, ?> protocol) {
return fill1_21_4(protocol).reader("tinted_leaves", Readers.COLOR);
}
public static void fill1_21_9(final Protocol<?, ?, ?, ?> protocol) {
fill1_21_5(protocol)
.reader("dragon_breath", Readers.POWER)
.reader("effect", Readers.SPELL)
.reader("instant_effect", Readers.SPELL)
.reader("flash", Readers.COLOR);
}
}
}
@@ -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();
@@ -60,7 +60,7 @@ public class InformativeException extends RuntimeException {
@Override
public String getMessage() {
final StringBuilder builder = new StringBuilder("Please report this on the Via support Discord or open an issue on the relevant GitHub repository\n");
final StringBuilder builder = new StringBuilder("Please report the full error (!) from the console on the Via support Discord or open an issue on the relevant GitHub repository.\n");
boolean first = true;
for (final DataEntry entry : dataEntries) {
if (!first) {
+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
}
@@ -49,6 +49,20 @@ public final class NMSUtil {
}
}
public static Class<?> nms(String className, String... fallbackFullClassNames) throws ClassNotFoundException {
try {
return Class.forName(NMS + "." + className);
} catch (ClassNotFoundException ignored) {
}
for (final String fallbackFullClassName : fallbackFullClassNames) {
try {
return Class.forName(fallbackFullClassName);
} catch (ClassNotFoundException ignored) {
}
}
throw new ClassNotFoundException(className);
}
public static Class<?> obc(String className) throws ClassNotFoundException {
return Class.forName(BASE + "." + className);
}
@@ -105,7 +105,8 @@ public class BukkitViaInjector extends LegacyViaInjector {
// Grab the ping class and find the field to access it
Class<?> pingClazz = NMSUtil.nms(
"ServerPing",
"net.minecraft.network.protocol.status.ServerPing"
"net.minecraft.network.protocol.status.ServerPing",
"net.minecraft.network.protocol.status.ServerStatus"
);
Object ping = null;
for (Field field : serverClazz.getDeclaredFields()) {
@@ -120,7 +121,8 @@ public class BukkitViaInjector extends LegacyViaInjector {
// Now get the ServerData inside ServerPing
Class<?> serverDataClass = NMSUtil.nms(
"ServerPing$ServerData",
"net.minecraft.network.protocol.status.ServerPing$ServerData"
"net.minecraft.network.protocol.status.ServerPing$ServerData",
"net.minecraft.network.protocol.status.ServerStatus$Version"
);
Object serverData = null;
for (Field field : pingClazz.getDeclaredFields()) {
@@ -155,7 +157,8 @@ public class BukkitViaInjector extends LegacyViaInjector {
);
Class<?> connectionClass = NMSUtil.nms(
"ServerConnection",
"net.minecraft.server.network.ServerConnection"
"net.minecraft.server.network.ServerConnection",
"net.minecraft.server.network.ServerConnectionListener"
);
Object server = ReflectionUtil.invokeStatic(serverClass, "getServer");
@@ -2,23 +2,18 @@
* 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:
* 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.
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* 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.
*
* 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.
* 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.api.protocol;
@@ -39,10 +34,15 @@ import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypeMap;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.MappingDataListener;
import com.viaversion.viaversion.api.rewriter.Rewriter;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.ComponentRewriterBase;
import com.viaversion.viaversion.util.ProtocolLogger;
import com.viaversion.viaversion.util.ProtocolUtil;
import java.util.HashMap;
@@ -74,6 +74,8 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
private final Map<Class<?>, Object> storedObjects = new HashMap<>();
private boolean initialized;
private ProtocolLogger logger;
private ProtocolVersion serverVersion;
private ProtocolVersion clientVersion;
@Deprecated
protected AbstractProtocol() {
@@ -104,6 +106,11 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
if (logger == null) {
logger = createLogger();
}
// Apply shared registrations based on protocol version range
// Run before registerPackets, so implementations have to call append intentionally
applySharedRegistrations();
registerPackets();
registerConfigurationChangeHandlers();
@@ -128,6 +135,13 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
}
}
/**
* Applies shared registrations. Can be overridden to remove or add registrations.
*/
protected void applySharedRegistrations() {
SharedRegistrations.defaultRegistrations().applyMatching(this);
}
protected ProtocolLogger createLogger() {
return new ProtocolLogger(getClass());
}
@@ -177,6 +191,20 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
}
}
@Override
public void replaceClientbound(final CU type, @Nullable final PacketHandler handler) {
final PacketMapping mapping = clientboundMappings.mappedPacket(type.state(), type.getId());
Preconditions.checkNotNull(mapping, "Packet %s has no handler to replace", type);
mapping.setHandler(handler);
}
@Override
public void replaceServerbound(final SU type, @Nullable final PacketHandler handler) {
final PacketMapping mapping = serverboundMappings.mappedPacket(type.state(), type.getId());
Preconditions.checkNotNull(mapping, "Packet %s has no handler to replace", type);
mapping.setHandler(handler);
}
private <U extends PacketType, M extends PacketType> void registerPacketIdChanges(
Map<State, PacketTypeMap<U>> unmappedPacketTypes,
Map<State, PacketTypeMap<M>> mappedPacketTypes,
@@ -214,6 +242,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
@Override
public final void loadMappingData() {
getMappingData().load();
initialize();
onMappingDataLoaded();
}
@@ -289,6 +318,46 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
return packetTypesProvider.unmappedClientboundType(State.CONFIGURATION, "FINISH_CONFIGURATION");
}
/**
* Returns the server protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the server protocol version
*/
public @Nullable ProtocolVersion getServerVersion() {
return serverVersion;
}
/**
* Sets the server protocol version for this protocol.
* Called by the protocol manager before {@link #initialize()}.
*
* @param serverVersion the server protocol version
*/
public void setServerVersion(final ProtocolVersion serverVersion) {
this.serverVersion = serverVersion;
}
/**
* Returns the client protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the client protocol version for this protocol
*/
public @Nullable ProtocolVersion getClientVersion() {
return clientVersion;
}
/**
* Sets the client protocol version for this protocol.
* Called by the protocol manager before {@link #initialize()}.
*
* @param clientVersion the client protocol version for this protocol
*/
public void setClientVersion(final ProtocolVersion clientVersion) {
this.clientVersion = clientVersion;
}
// ---------------------------------------------------------------------------------
@Override
@@ -297,7 +366,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
PacketMapping packetMapping = PacketMapping.of(mappedPacketId, handler);
if (!override && serverboundMappings.hasMapping(state, unmappedPacketId)) {
Via.getPlatform().getLogger().log(Level.WARNING, unmappedPacketId + " already registered!" +
" If this override is intentional, set override to true. Stacktrace: ", new Exception());
" If this override is intentional, use replaceServerbound instead. Stacktrace: ", new Exception());
}
serverboundMappings.addMapping(state, unmappedPacketId, packetMapping);
}
@@ -313,7 +382,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
PacketMapping packetMapping = PacketMapping.of(mappedPacketId, handler);
if (!override && clientboundMappings.hasMapping(state, unmappedPacketId)) {
Via.getPlatform().getLogger().log(Level.WARNING, unmappedPacketId + " already registered!" +
" If override is intentional, set override to true. Stacktrace: ", new Exception());
" If override is intentional, use replaceClientbound instead. Stacktrace: ", new Exception());
}
clientboundMappings.addMapping(state, unmappedPacketId, packetMapping);
}
@@ -373,8 +442,8 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
PacketMapping packetMapping = PacketMapping.of(mappedPacketType, handler);
if (!override && packetMappings.hasMapping(packetType)) {
getLogger().log(Level.WARNING, packetType + " already registered!" +
" If override is intentional, set override to true. Stacktrace: ", new Exception());
throw new IllegalArgumentException("Packet type " + packetType + " already registered! If override is intentional, use "
+ (packetType.direction() == Direction.SERVERBOUND ? "replaceServerbound" : "replaceClientbound") + " instead.");
}
packetMappings.addMapping(packetType, packetMapping);
}
@@ -443,6 +512,39 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
return logger;
}
@Override
public @Nullable TagRewriter<CU> getTagRewriter() {
return null;
}
@Override
public @Nullable ComponentRewriterBase<CU> getComponentRewriter() {
return null;
}
@Override
public com.viaversion.viaversion.rewriter.@Nullable ParticleRewriter<CU> getParticleRewriter() {
return null;
}
@Override
public com.viaversion.viaversion.rewriter.@Nullable EntityRewriter<CU, ?> getEntityRewriter() {
return null;
}
@Override
public com.viaversion.viaversion.rewriter.@Nullable ItemRewriter<CU, SU, ?> getItemRewriter() {
return null;
}
public com.viaversion.viaversion.rewriter.@Nullable BlockRewriter<CU> getBlockRewriter() {
return null;
}
public @Nullable RecipeDisplayRewriter<CU> getRecipeRewriter() {
return null;
}
private void printRemapError(Direction direction, State state, int unmappedPacketId, int mappedPacketId, InformativeException e) {
// Don't print errors during handshake/login/status
if (state != State.PLAY && direction == Direction.SERVERBOUND && !Via.getManager().debugHandler().enabled()) {
@@ -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) {
@@ -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
@@ -78,6 +78,7 @@ public final class ConnectionDetails {
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));
}
@@ -102,6 +103,7 @@ public final class ConnectionDetails {
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));
}
@@ -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;
}
@@ -0,0 +1,34 @@
/*
* 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.protocol;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.SimpleProtocol;
/**
* A simple protocol which does not have any packet types.
* <p>
* {@link AbstractProtocol} should be preferred over this class in most cases.
*/
public abstract class AbstractSimpleProtocol extends AbstractProtocol<SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes,
SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes> implements SimpleProtocol {
protected AbstractSimpleProtocol() {
super(null, null, null, null);
}
}
@@ -23,6 +23,7 @@ import com.google.common.collect.Range;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.ProtocolManager;
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
@@ -38,6 +39,7 @@ import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion;
import com.viaversion.viaversion.api.protocol.version.VersionType;
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
import com.viaversion.viaversion.protocol.packet.VersionedPacketTransformerImpl;
import com.viaversion.viaversion.protocol.shared_registration.def.DefaultRegistrations;
import com.viaversion.viaversion.protocols.base.InitialBaseProtocol;
import com.viaversion.viaversion.protocols.base.v1_16.ClientboundBaseProtocol1_16;
import com.viaversion.viaversion.protocols.base.v1_7.ClientboundBaseProtocol1_7;
@@ -76,6 +78,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;
@@ -94,6 +97,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -112,9 +116,7 @@ import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.logging.Level;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ProtocolManagerImpl implements ProtocolManager {
@@ -145,6 +147,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
worker.setName("Via-Mappingloader-" + threadIndex.incrementAndGet());
return worker;
}, ForkJoinWorkerThread.getDefaultUncaughtExceptionHandler(), true);
DefaultRegistrations.apply();
}
public void registerProtocols() {
@@ -213,6 +217,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
@@ -222,8 +228,11 @@ public class ProtocolManagerImpl implements ProtocolManager {
@Override
public void registerProtocol(Protocol protocol, List<ProtocolVersion> supportedClientVersion, ProtocolVersion serverVersion) {
// Register the protocol's handlers
protocol.initialize();
// Set the server version on AbstractProtocol instances before initialization
if (protocol instanceof AbstractProtocol<?, ?, ?, ?> abstractProtocol) {
abstractProtocol.setServerVersion(serverVersion);
abstractProtocol.setClientVersion(supportedClientVersion.stream().max(ProtocolVersion::compareTo).orElseThrow());
}
// Clear cache as this may make new routes.
if (!pathCache.isEmpty()) {
@@ -245,14 +254,22 @@ public class ProtocolManagerImpl implements ProtocolManager {
refreshVersions();
}
if (protocol.hasMappingDataToLoad()) {
if (mappingLoaderExecutor != null) {
// Submit mapping data loading
addMappingLoaderFuture(protocol.getClass(), protocol::loadMappingData);
// Load mapping data and register the protocol's handlers
if (!protocol.hasMappingDataToLoad()) {
protocol.initialize();
return;
}
// Submit mapping data loading
if (mappingLoaderExecutor != null) {
if (protocol.dependsOn() != null) {
addMappingLoaderFuture(protocol.getClass(), protocol.dependsOn(), protocol::loadMappingData);
} else {
// Late protocol adding - just do it on the current thread
protocol.loadMappingData();
addMappingLoaderFuture(protocol.getClass(), protocol::loadMappingData);
}
} else {
// Late protocol adding - just do it on the current thread
protocol.loadMappingData();
}
}
@@ -481,7 +498,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
}
@Override
public boolean checkForMappingCompletion() {
public boolean checkForMappingCompletion(final boolean propagateErrors) {
mappingLoaderLock.readLock().lock();
try {
if (mappingsLoaded) {
@@ -493,6 +510,9 @@ public class ProtocolManagerImpl implements ProtocolManager {
if (!future.isDone()) {
return false;
}
if (propagateErrors) {
future.join();
}
}
shutdownLoaderExecutor();
@@ -504,7 +524,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
@Override
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Runnable runnable) {
CompletableFuture<Void> future = CompletableFuture.runAsync(runnable, mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
CompletableFuture<Void> future = CompletableFuture.runAsync(runnable, mappingLoaderExecutor)
.whenComplete(($, t) -> logIfErrored(protocolClass, t));
mappingLoaderLock.writeLock().lock();
try {
@@ -516,8 +537,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
@Override
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Class<? extends Protocol> dependsOn, Runnable runnable) {
CompletableFuture<Void> future = getMappingLoaderFuture(dependsOn)
.whenCompleteAsync((v, throwable) -> runnable.run(), mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
CompletableFuture<Void> future = getMappingLoaderFuture(dependsOn).thenRunAsync(runnable, mappingLoaderExecutor)
.whenComplete(($, t) -> logIfErrored(protocolClass, t));
mappingLoaderLock.writeLock().lock();
try {
@@ -568,10 +589,9 @@ public class ProtocolManagerImpl implements ProtocolManager {
MappingDataLoader.INSTANCE.clearCache();
}
private Function<Throwable, Void> mappingLoaderThrowable(Class<? extends Protocol> protocolClass) {
return throwable -> {
Via.getPlatform().getLogger().log(Level.SEVERE, "Error during mapping loading of " + protocolClass.getSimpleName(), throwable);
return null;
};
private void logIfErrored(final Class<? extends Protocol> protocolClass, @Nullable final Throwable throwable) {
if (throwable != null) {
Via.getPlatform().getLogger().log(Level.SEVERE, "Error during loading of " + protocolClass.getSimpleName(), throwable);
}
}
}
@@ -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{" +
@@ -0,0 +1,23 @@
/*
* 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.protocol.shared_registration;
public enum PacketBound {
ADDED_AT_MIN,
REMOVED_AT_MAX
}
@@ -0,0 +1,151 @@
/*
* 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.protocol.shared_registration;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.protocol.version.VersionType;
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations.RegistrationAction;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
public final class RegistrationBuilder {
private final List<VersionedTemplateGroup> groups = new ArrayList<>();
private final SharedRegistrations registrations;
private VersionType versionType;
RegistrationBuilder(final SharedRegistrations registrations) {
this.registrations = registrations;
}
/**
* Adds a registration for an open-ended version range.
*
* @param min minimum version, inclusive
* @param action registration action
* @return this
*/
public RegistrationBuilder since(final ProtocolVersion min, final RegistrationAction<?, ?> action) {
checkVersionType(min);
groups.add(new VersionedTemplateGroup(action, min, null));
return this;
}
/**
* Adds a registration for a version range.
*
* @param min minimum version, inclusive
* @param max maximum version, exclusive
* @param action registration action
* @return this
*/
public RegistrationBuilder range(final ProtocolVersion min, final ProtocolVersion max, final RegistrationAction<?, ?> action) {
checkVersionType(min);
checkVersionType(max);
groups.add(new VersionedTemplateGroup(action, min, max));
return this;
}
public <CU extends ClientboundPacketType, SU extends ServerboundPacketType> RegistrationBuilder ranges(
final ProtocolVersion min, final Consumer<RangesBuilder<CU, SU>> consumer
) {
consumer.accept(new RangesBuilder<>(min));
return this;
}
public <CU extends ClientboundPacketType, SU extends ServerboundPacketType, R> RegistrationBuilder ranges(
final Function<RegistrationContext<CU, SU>, R> adapter, final ProtocolVersion min,
final Consumer<TypedRangesBuilder<CU, SU, R>> consumer
) {
consumer.accept(new TypedRangesBuilder<>(adapter, min));
return this;
}
public void register() {
registrations.register(versionType, groups);
}
private void checkVersionType(final ProtocolVersion version) {
if (versionType == null) {
versionType = version.getVersionType();
} else if (versionType != version.getVersionType()) {
throw new IllegalArgumentException("Cannot mix different version types in the same registration builder");
}
}
public class RangesBuilder<CU extends ClientboundPacketType, SU extends ServerboundPacketType> {
private ProtocolVersion currentMin;
private boolean completed;
private RangesBuilder(final ProtocolVersion min) {
this.currentMin = min;
}
public RangesBuilder<CU, SU> to(final ProtocolVersion max, final RegistrationAction<CU, SU> action) {
Preconditions.checkState(!completed, "Range chain already completed");
RegistrationBuilder.this.range(currentMin, max, action);
currentMin = max;
return this;
}
public RegistrationBuilder since(final RegistrationAction<CU, SU> action) {
Preconditions.checkState(!completed, "Range chain already completed");
completed = true;
return RegistrationBuilder.this.since(currentMin, action);
}
}
public final class TypedRangesBuilder<CU extends ClientboundPacketType, SU extends ServerboundPacketType, R> extends RangesBuilder<CU, SU> {
private final Function<RegistrationContext<CU, SU>, R> adapter;
private TypedRangesBuilder(final Function<RegistrationContext<CU, SU>, R> adapter, final ProtocolVersion min) {
super(min);
this.adapter = adapter;
}
public TypedRangesBuilder<CU, SU, R> to(final ProtocolVersion max, final TypedRegistrationAction<CU, SU, R> action) {
to(max, wrapAction(action));
return this;
}
public TypedRangesBuilder<CU, SU, R> since(final TypedRegistrationAction<CU, SU, R> action) {
since(wrapAction(action));
return this;
}
private RegistrationAction<CU, SU> wrapAction(final TypedRegistrationAction<CU, SU, R> action) {
return ctx -> {
final R rewriter = adapter.apply(ctx);
if (rewriter != null) {
action.accept(ctx, rewriter);
}
};
}
}
@FunctionalInterface
public interface TypedRegistrationAction<CU extends ClientboundPacketType, SU extends ServerboundPacketType, R> {
void accept(RegistrationContext<CU, SU> ctx, R r);
}
}
@@ -0,0 +1,127 @@
/*
* 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.protocol.shared_registration;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import java.util.function.Consumer;
import org.checkerframework.checker.nullness.qual.Nullable;
public record RegistrationContext<CU extends ClientboundPacketType, SU extends ServerboundPacketType>(
AbstractProtocol<CU, ?, ?, SU> protocol,
ProtocolVersion min,
@Nullable ProtocolVersion max
) {
public <P extends AbstractProtocol<CU, ?, ?, SU>> P protocol(@SuppressWarnings("unused") final Class<P> protocolClass) {
//noinspection unchecked
return (P) protocol;
}
public <P extends AbstractProtocol<CU, ?, ?, SU>> P castProtocol() {
//noinspection unchecked
return (P) protocol;
}
public void clientbound(final ClientboundPacketType type, final Consumer<CU> action) {
action.accept(clientboundPacketType(type));
}
public void clientbound(final ClientboundPacketType type, final Consumer<CU> action, final PacketBound... markers) {
if (!shouldSkip(markers)) {
action.accept(clientboundPacketType(type));
}
}
public void clientboundHandler(final ClientboundPacketType type, final PacketHandler handler) {
protocol.registerClientbound(clientboundPacketType(type), handler);
}
public void clientboundHandler(final ClientboundPacketType type, final PacketHandler handler, final PacketBound... markers) {
if (!shouldSkip(markers)) {
protocol.registerClientbound(clientboundPacketType(type), handler);
}
}
public void serverbound(final ServerboundPacketType type, final Consumer<SU> action) {
action.accept(serverboundPacketType(type));
}
public void serverbound(final ServerboundPacketType type, final Consumer<SU> action, final PacketBound... markers) {
if (!shouldSkip(markers)) {
action.accept(serverboundPacketType(type));
}
}
public void serverboundHandler(final ServerboundPacketType type, final PacketHandler handler) {
protocol.registerServerbound(serverboundPacketType(type), handler);
}
public void serverboundHandler(final ServerboundPacketType type, final PacketHandler handler, final PacketBound... markers) {
if (!shouldSkip(markers)) {
protocol.registerServerbound(serverboundPacketType(type), handler);
}
}
private boolean shouldSkip(final PacketBound... markers) {
if (markers.length == 0) {
return false;
}
final ProtocolVersion serverVersion = protocol.getServerVersion();
final ProtocolVersion clientVersion = protocol.getClientVersion();
final ProtocolVersion lowerVersion = serverVersion.olderThan(clientVersion) ? serverVersion : clientVersion;
final ProtocolVersion higherVersion = serverVersion.newerThan(clientVersion) ? serverVersion : clientVersion;
for (final PacketBound marker : markers) {
switch (marker) {
case ADDED_AT_MIN -> {
if (lowerVersion.olderThan(min)) {
return true;
}
}
case REMOVED_AT_MAX -> {
Preconditions.checkArgument(max != null, "Cannot use REMOVED_AT_MAX in an open-ended range");
if (higherVersion.newerThanOrEqualTo(max)) {
return true;
}
}
}
}
return false;
}
private SU serverboundPacketType(final ServerboundPacketType genericPacketType) {
final SU type = protocol.getPacketTypesProvider().unmappedServerboundType(genericPacketType.state(), genericPacketType.getName());
if (type == null) {
throw new IllegalArgumentException("Could not find serverbound packet type for " + genericPacketType.state() + " " + genericPacketType.getName());
}
return type;
}
private CU clientboundPacketType(final ClientboundPacketType genericPacketType) {
final CU type = protocol.getPacketTypesProvider().unmappedClientboundType(genericPacketType.state(), genericPacketType.getName());
if (type == null) {
throw new IllegalArgumentException("Could not find clientbound packet type for " + genericPacketType.state() + " " + genericPacketType.getName() + " in " + protocol.getClass().getSimpleName());
}
return type;
}
}
@@ -0,0 +1,107 @@
/*
* 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.protocol.shared_registration;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.protocol.version.VersionType;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.EnumMap;
import java.util.List;
/**
* Central registry for shared packet registrations that are automatically applied
* to protocols based on their version range.
* <p>
* Registrations are done BEFORE registerPackets in {@link AbstractProtocol}.
*/
public final class SharedRegistrations {
private static final SharedRegistrations DEFAULT_REGISTRATIONS = new SharedRegistrations();
private final EnumMap<VersionType, List<VersionedTemplateGroup>> versionedTemplates = new EnumMap<>(VersionType.class);
/**
* Returns the default ViaVersion registration set.
*/
public static SharedRegistrations defaultRegistrations() {
return DEFAULT_REGISTRATIONS;
}
/**
* Creates an independent shared registration set that external projects can populate and apply.
*/
public static SharedRegistrations create() {
return new SharedRegistrations();
}
public RegistrationBuilder registrations() {
return new RegistrationBuilder(this);
}
/**
* Applies all shared registrations whose version range matches the given protocol.
*
* @param protocol the protocol to apply shared registrations to
*/
public void applyMatching(final AbstractProtocol<?, ?, ?, ?> protocol) {
if (protocol.isBaseProtocol()) {
return;
}
final ProtocolVersion version = protocol.getServerVersion();
if (version.getVersionType() != protocol.getClientVersion().getVersionType()) {
// Built on continuous version ranges
return;
}
final List<VersionedTemplateGroup> groups = versionedTemplates.get(version.getVersionType());
if (groups == null) {
return;
}
for (final VersionedTemplateGroup group : groups) {
if (group.min().newerThan(version)) { // TODO binary search?
// Sorted by the minimum, so we can stop early if we're out
break;
}
if (group.max() != null && version.newerThanOrEqualTo(group.max())) {
continue;
}
final RegistrationContext<?, ?> context = new RegistrationContext<>(protocol, group.min(), group.max());
//noinspection unchecked,rawtypes
((RegistrationAction) group.action()).accept(context);
}
}
@FunctionalInterface
public interface RegistrationAction<CU extends ClientboundPacketType, SU extends ServerboundPacketType> {
void accept(RegistrationContext<CU, SU> context);
}
void register(final VersionType versionType, final List<VersionedTemplateGroup> toAdd) {
final List<VersionedTemplateGroup> groups = versionedTemplates.computeIfAbsent(versionType, $ -> new ArrayList<>());
groups.addAll(toAdd);
groups.sort(Comparator.comparing(VersionedTemplateGroup::min, Comparator.nullsFirst(Comparator.naturalOrder())));
}
}
@@ -0,0 +1,32 @@
/*
* 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.protocol.shared_registration;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations.RegistrationAction;
record VersionedTemplateGroup(
RegistrationAction<?, ?> action,
ProtocolVersion min,
ProtocolVersion max
) {
public boolean contains(final ProtocolVersion version) {
return version.newerThanOrEqualTo(min) && (max == null || version.olderThan(max));
}
}
@@ -0,0 +1,95 @@
/*
* 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.protocol.shared_registration.def;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_14_3to1_14_4.packet.ClientboundPackets1_14_4;
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2;
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
final class BlockRegistrations {
static <CU extends ClientboundPacketType> void registerBlockPackets1_13(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
common1_13(ctx, br);
ctx.clientbound(ClientboundPackets1_13.CHUNK_BLOCKS_UPDATE, br::registerChunkBlocksUpdate);
}
private static <CU extends ClientboundPacketType> void common1_13(RegistrationContext<CU, ?> ctx, BlockRewriter<CU> br) {
ctx.clientbound(ClientboundPackets1_13.BLOCK_EVENT, br::registerBlockEvent);
ctx.clientbound(ClientboundPackets1_13.BLOCK_UPDATE, br::registerBlockUpdate);
ctx.clientbound(ClientboundPackets1_13.LEVEL_EVENT, br::registerLevelEvent1_13);
}
static <CU extends ClientboundPacketType> void registerBlockPackets1_14_4(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
common1_13(ctx, br);
ctx.clientbound(ClientboundPackets1_14_4.CHUNK_BLOCKS_UPDATE, br::registerChunkBlocksUpdate, PacketBound.REMOVED_AT_MAX);
ctx.clientbound(ClientboundPackets1_14_4.BLOCK_BREAK_ACK, br::registerBlockBreakAck, PacketBound.ADDED_AT_MIN);
}
static <CU extends ClientboundPacketType> void registerBlockPackets1_16_2(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
common1_13(ctx, br);
ctx.clientbound(ClientboundPackets1_16_2.BLOCK_BREAK_ACK, br::registerBlockBreakAck);
ctx.clientbound(ClientboundPackets1_16_2.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate, PacketBound.ADDED_AT_MIN);
}
static <CU extends ClientboundPacketType> void registerBlockPackets1_18(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
common1_13(ctx, br);
ctx.clientbound(ClientboundPackets1_18.BLOCK_BREAK_ACK, br::registerBlockBreakAck, PacketBound.REMOVED_AT_MAX);
ctx.clientbound(ClientboundPackets1_18.LEVEL_CHUNK_WITH_LIGHT, br::registerLevelChunk1_18, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_18.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate);
ctx.clientbound(ClientboundPackets1_18.BLOCK_ENTITY_DATA, br::registerBlockEntityData1_18);
}
static <CU extends ClientboundPacketType> void registerBlockPackets1_19(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
common1_19(ctx, br);
ctx.clientbound(ClientboundPackets1_19.LEVEL_EVENT, br::registerLevelEvent1_13);
ctx.clientbound(ClientboundPackets1_19.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate);
}
private static <CU extends ClientboundPacketType> void common1_19(RegistrationContext<CU, ?> ctx, BlockRewriter<CU> br) {
ctx.clientbound(ClientboundPackets1_19.BLOCK_EVENT, br::registerBlockEvent);
ctx.clientbound(ClientboundPackets1_19.BLOCK_UPDATE, br::registerBlockUpdate);
ctx.clientbound(ClientboundPackets1_19.LEVEL_CHUNK_WITH_LIGHT, br::registerLevelChunk1_18);
ctx.clientbound(ClientboundPackets1_19.BLOCK_ENTITY_DATA, br::registerBlockEntityData1_18);
}
static <CU extends ClientboundPacketType> void registerBlockPackets1_20(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
common1_19(ctx, br);
ctx.clientbound(ClientboundPackets1_19_4.LEVEL_EVENT, br::registerLevelEvent1_13);
ctx.clientbound(ClientboundPackets1_19_4.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate1_20);
}
static <CU extends ClientboundPacketType> void registerBlockPackets1_21(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
common1_19(ctx, br);
ctx.clientbound(ClientboundPackets1_21.LEVEL_EVENT, br::registerLevelEvent1_21);
ctx.clientbound(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate1_20);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> BlockRewriter<CU> block(final RegistrationContext<CU, SU> ctx) {
return ctx.protocol().getBlockRewriter();
}
}
@@ -0,0 +1,110 @@
/*
* 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.protocol.shared_registration.def;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations;
public final class DefaultRegistrations {
public static void apply() {
SharedRegistrations.defaultRegistrations().registrations()
.ranges(EntityRegistrations::entity, ProtocolVersion.v1_13, b -> b
.to(ProtocolVersion.v1_14_4, EntityRegistrations::registerEntityPackets1_13)
.to(ProtocolVersion.v1_16_2, EntityRegistrations::registerEntityPackets1_14_4)
.to(ProtocolVersion.v1_17_1, EntityRegistrations::registerEntityPackets1_16_2)
.to(ProtocolVersion.v1_19, EntityRegistrations::registerEntityPackets1_17_1)
.to(ProtocolVersion.v1_20_5, EntityRegistrations::registerEntityPackets1_19)
.to(ProtocolVersion.v1_21_4, EntityRegistrations::registerEntityPackets1_20_5)
.to(ProtocolVersion.v1_21_9, EntityRegistrations::registerEntityPackets1_21_4)
.since(EntityRegistrations::registerEntityPackets1_21_9)
)
.ranges(ItemRegistrations::item, ProtocolVersion.v1_13, b -> b
.to(ProtocolVersion.v1_14, ItemRegistrations::registerItemPackets1_13)
.to(ProtocolVersion.v1_14_4, ItemRegistrations::registerItemPackets1_14)
.to(ProtocolVersion.v1_16, ItemRegistrations::registerItemPackets1_14_4)
.to(ProtocolVersion.v1_17_1, ItemRegistrations::registerItemPackets1_16)
.to(ProtocolVersion.v1_19_1, ItemRegistrations::registerItemPackets1_17_1)
.to(ProtocolVersion.v1_20_3, ItemRegistrations::registerItemPackets1_19_1)
.to(ProtocolVersion.v1_20_5, ItemRegistrations::registerItemPackets1_20_3)
.to(ProtocolVersion.v1_21, ItemRegistrations::registerItemPackets1_20_5)
.to(ProtocolVersion.v1_21_2, ItemRegistrations::registerItemPackets1_21)
.to(ProtocolVersion.v1_21_5, ItemRegistrations::registerItemPackets1_21_2)
)
.ranges(ItemRegistrations::structuredItem, ProtocolVersion.v1_21_5, b -> b
.to(ProtocolVersion.v1_21_6, ItemRegistrations::registerItemPackets1_21_5)
.since(ItemRegistrations::registerItemPackets1_21_6)
)
.ranges(BlockRegistrations::block, ProtocolVersion.v1_13, steps -> steps
.to(ProtocolVersion.v1_14_4, BlockRegistrations::registerBlockPackets1_13)
.to(ProtocolVersion.v1_16_2, BlockRegistrations::registerBlockPackets1_14_4)
.to(ProtocolVersion.v1_18, BlockRegistrations::registerBlockPackets1_16_2)
.to(ProtocolVersion.v1_19, BlockRegistrations::registerBlockPackets1_18)
.to(ProtocolVersion.v1_20, BlockRegistrations::registerBlockPackets1_19)
.to(ProtocolVersion.v1_21, BlockRegistrations::registerBlockPackets1_20)
.since(BlockRegistrations::registerBlockPackets1_21)
)
.ranges(ParticleRegistrations::particle, ProtocolVersion.v1_13, steps -> steps
.to(ProtocolVersion.v1_15_2, ParticleRegistrations::registerParticlePackets1_13)
.to(ProtocolVersion.v1_19, ParticleRegistrations::registerParticlePackets1_15_2)
.to(ProtocolVersion.v1_20, ParticleRegistrations::registerParticlePackets1_19)
.to(ProtocolVersion.v1_20_5, ParticleRegistrations::registerParticlePackets1_20)
.to(ProtocolVersion.v1_21_2, ParticleRegistrations::registerParticlePackets1_20_5)
.to(ProtocolVersion.v1_21_4, ParticleRegistrations::registerParticlePackets1_21_2)
.to(ProtocolVersion.v1_21_9, ParticleRegistrations::registerParticlePackets1_21_4)
.since(ParticleRegistrations::registerParticlePackets1_21_9)
)
.ranges(TextComponentRegistrations::text, ProtocolVersion.v1_12_2, b -> b
.to(ProtocolVersion.v1_14, TextComponentRegistrations::registerComponents1_12_2)
.to(ProtocolVersion.v1_16_2, TextComponentRegistrations::registerComponents1_14)
.to(ProtocolVersion.v1_17, TextComponentRegistrations::registerComponents1_16_2)
.to(ProtocolVersion.v1_19, TextComponentRegistrations::registerComponents1_17)
.to(ProtocolVersion.v1_20_3, TextComponentRegistrations::registerComponents1_19)
.to(ProtocolVersion.v1_20_5, TextComponentRegistrations::registerComponents1_20_3)
.to(ProtocolVersion.v1_21, TextComponentRegistrations::registerComponents1_20_5)
.to(ProtocolVersion.v1_21_4, TextComponentRegistrations::registerComponents1_21)
.to(ProtocolVersion.v1_21_5, TextComponentRegistrations::registerComponents1_21_4)
)
.ranges(TextComponentRegistrations::nbtText, ProtocolVersion.v1_21_5, b -> b
.since(TextComponentRegistrations::registerComponents1_21_5)
)
.ranges(ProtocolVersion.v1_17_1, sbeps -> sbeps
.to(ProtocolVersion.v1_20_2, RegistryRegistrations::registerTags1_17_1)
.since(RegistryRegistrations::registerTags1_20_2)
)
.ranges(ProtocolVersion.v1_10, b -> b
.to(ProtocolVersion.v1_14, RegistryRegistrations::registerSounds1_10)
.to(ProtocolVersion.v1_19_3, RegistryRegistrations::registerSounds1_14)
.since(RegistryRegistrations::registerSounds1_19_3)
)
.since(ProtocolVersion.v1_13, RegistryRegistrations::registerStatistics1_13)
.since(ProtocolVersion.v1_19, RegistryRegistrations::registerCommands1_19)
.since(ProtocolVersion.v1_21, RegistryRegistrations::registerRegistryData1_21)
.since(ProtocolVersion.v1_21, RegistryRegistrations::registerAttributes1_21)
.since(ProtocolVersion.v1_21_2, RegistryRegistrations::registerRecipePackets1_21_2)
.register();
}
}
@@ -0,0 +1,96 @@
/*
* 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.protocol.shared_registration.def;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_14_3to1_14_4.packet.ClientboundPackets1_14_4;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
final class EntityRegistrations {
static <CU extends ClientboundPacketType> void registerEntityPackets1_13(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
ctx.clientbound(ClientboundPackets1_13.REMOVE_ENTITIES, er::registerRemoveEntities);
}
static <CU extends ClientboundPacketType> void registerEntityPackets1_14_4(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
ctx.clientbound(ClientboundPackets1_14_4.REMOVE_ENTITIES, er::registerRemoveEntities);
ctx.clientbound(ClientboundPackets1_14_4.ADD_ENTITY, er::registerTrackerWithData);
ctx.clientbound(ClientboundPackets1_14_4.ADD_MOB, er::registerTracker);
}
static <CU extends ClientboundPacketType> void registerEntityPackets1_16_2(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
// remove_entities got temporarily changed to only take a single entity...
ctx.clientbound(ClientboundPackets1_14_4.ADD_ENTITY, er::registerTrackerWithData);
ctx.clientbound(ClientboundPackets1_14_4.ADD_MOB, er::registerTracker);
}
static <CU extends ClientboundPacketType> void registerEntityPackets1_17_1(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
ctx.clientbound(ClientboundPackets1_14_4.REMOVE_ENTITIES, er::registerRemoveEntities);
ctx.clientbound(ClientboundPackets1_14_4.ADD_ENTITY, er::registerTrackerWithData);
ctx.clientbound(ClientboundPackets1_14_4.ADD_MOB, er::registerTracker, PacketBound.REMOVED_AT_MAX);
}
static <CU extends ClientboundPacketType> void registerEntityPackets1_19(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
ctx.clientbound(ClientboundPackets1_9.REMOVE_ENTITIES, er::registerRemoveEntities);
ctx.clientbound(ClientboundPackets1_19.ADD_ENTITY, er::registerTrackerWithData1_19);
}
static <CU extends ClientboundPacketType> void registerEntityPackets1_20_5(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
common1_20_5(ctx, er);
ctx.clientbound(ClientboundPackets1_19.ADD_ENTITY, er::registerTrackerWithData1_19);
}
static <CU extends ClientboundPacketType> void registerEntityPackets1_21_4(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
common1_20_5(ctx, er);
registerGameModeTrackers1_21_4(ctx, er);
ctx.clientbound(ClientboundPackets1_21_2.ADD_ENTITY, er::registerTrackerWithData1_19);
}
static <CU extends ClientboundPacketType> void registerEntityPackets1_21_9(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
common1_20_5(ctx, er);
registerGameModeTrackers1_21_4(ctx, er);
ctx.clientbound(ClientboundPackets1_21_9.ADD_ENTITY, er::registerTrackerWithData1_21_9);
}
private static <CU extends ClientboundPacketType> void common1_20_5(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
ctx.clientbound(ClientboundPackets1_20_5.SET_ENTITY_DATA, er::registerSetEntityData);
ctx.clientbound(ClientboundPackets1_20_5.REMOVE_ENTITIES, er::registerRemoveEntities);
ctx.clientbound(ClientboundPackets1_20_5.LOGIN, er::registerLogin1_20_5);
ctx.clientbound(ClientboundPackets1_20_5.RESPAWN, er::registerRespawn1_20_5);
}
private static <CU extends ClientboundPacketType> void registerGameModeTrackers1_21_4(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
ctx.clientbound(ClientboundPackets1_21_2.GAME_EVENT, er::registerGameEvent);
ctx.clientbound(ClientboundPackets1_21_2.PLAYER_ABILITIES, er::registerPlayerAbilities);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> EntityRewriter<CU, ?> entity(final RegistrationContext<CU, SU> ctx) {
return ctx.protocol().getEntityRewriter();
}
}
@@ -0,0 +1,185 @@
/*
* 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.protocol.shared_registration.def;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ServerboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.v1_14_3to1_14_4.packet.ClientboundPackets1_14_4;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
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_19_1to1_19_3.packet.ServerboundPackets1_19_3;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPackets1_19_1;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ServerboundPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPackets1_21_5;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ServerboundPackets1_21_5;
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.ClientboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.ItemRewriter;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
final class ItemRegistrations {
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_13(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
common1_13(ctx, ir);
ctx.clientbound(ClientboundPackets1_13.SET_EQUIPPED_ITEM, ir::registerSetEquippedItem);
}
private static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void common1_13(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_13.CONTAINER_SET_DATA, ir::registerContainerSetData);
ctx.clientbound(ClientboundPackets1_13.CONTAINER_SET_SLOT, ir::registerSetSlot);
ctx.clientbound(ClientboundPackets1_13.CONTAINER_SET_CONTENT, ir::registerSetContent);
ctx.clientbound(ClientboundPackets1_13.UPDATE_ADVANCEMENTS, ir::registerAdvancements);
ctx.clientbound(ClientboundPackets1_13.COOLDOWN, ir::registerCooldown);
ctx.serverbound(ServerboundPackets1_13.CONTAINER_CLICK, ir::registerContainerClick);
ctx.serverbound(ServerboundPackets1_13.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_14(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
common1_13(ctx, ir);
ctx.clientbound(ClientboundPackets1_14.SET_EQUIPPED_ITEM, ir::registerSetEquippedItem);
ctx.clientbound(ClientboundPackets1_14.OPEN_SCREEN, ir::registerOpenScreen);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_14_4(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
common1_13(ctx, ir);
ctx.clientbound(ClientboundPackets1_14_4.SET_EQUIPPED_ITEM, ir::registerSetEquippedItem, PacketBound.REMOVED_AT_MAX);
ctx.clientbound(ClientboundPackets1_14_4.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_14_4.MERCHANT_OFFERS, ir::registerMerchantOffers1_14_4);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_16(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
common1_13(ctx, ir);
ctx.clientbound(ClientboundPackets1_16.SET_EQUIPMENT, ir::registerSetEquipment, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_16.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_16.MERCHANT_OFFERS, ir::registerMerchantOffers1_14_4);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_17_1(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_17_1.CONTAINER_SET_DATA, ir::registerContainerSetData);
ctx.clientbound(ClientboundPackets1_17_1.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
ctx.clientbound(ClientboundPackets1_17_1.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
ctx.clientbound(ClientboundPackets1_17_1.UPDATE_ADVANCEMENTS, ir::registerAdvancements);
ctx.clientbound(ClientboundPackets1_17_1.COOLDOWN, ir::registerCooldown);
ctx.serverbound(ServerboundPackets1_17.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
ctx.serverbound(ServerboundPackets1_17.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
ctx.clientbound(ClientboundPackets1_17_1.SET_EQUIPMENT, ir::registerSetEquipment);
ctx.clientbound(ClientboundPackets1_17_1.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_17_1.MERCHANT_OFFERS, ir::registerMerchantOffers1_14_4);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_19_1(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_19_1.CONTAINER_SET_DATA, ir::registerContainerSetData);
ctx.clientbound(ClientboundPackets1_19_1.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
ctx.clientbound(ClientboundPackets1_19_1.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
ctx.clientbound(ClientboundPackets1_19_1.UPDATE_ADVANCEMENTS, ir::registerAdvancements);
ctx.clientbound(ClientboundPackets1_19_1.COOLDOWN, ir::registerCooldown);
ctx.serverbound(ServerboundPackets1_19_3.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
ctx.serverbound(ServerboundPackets1_19_3.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
ctx.clientbound(ClientboundPackets1_19_1.SET_EQUIPMENT, ir::registerSetEquipment);
ctx.clientbound(ClientboundPackets1_19_1.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_19_1.MERCHANT_OFFERS, ir::registerMerchantOffers1_19);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_20_3(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_DATA, ir::registerContainerSetData);
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
ctx.clientbound(ClientboundPackets1_20_5.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
ctx.clientbound(ClientboundPackets1_20_3.COOLDOWN, ir::registerCooldown);
ctx.serverbound(ServerboundPackets1_20_3.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
ctx.serverbound(ServerboundPackets1_20_2.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
ctx.clientbound(ClientboundPackets1_20_5.SET_EQUIPMENT, ir::registerSetEquipment);
ctx.clientbound(ClientboundPackets1_19_4.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_20_2.MERCHANT_OFFERS, ir::registerMerchantOffers1_19);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_20_5(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_DATA, ir::registerContainerSetData);
registerItemPackets1_21(ctx, ir);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_21.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
ctx.clientbound(ClientboundPackets1_21.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
ctx.clientbound(ClientboundPackets1_21.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
ctx.clientbound(ClientboundPackets1_21.COOLDOWN, ir::registerCooldown);
ctx.serverbound(ServerboundPackets1_20_5.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
ctx.serverbound(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
ctx.clientbound(ClientboundPackets1_21.SET_EQUIPMENT, ir::registerSetEquipment);
ctx.clientbound(ClientboundPackets1_21.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_21.MERCHANT_OFFERS, ir::registerMerchantOffers1_20_5);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21_2(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_21_2.CONTAINER_SET_SLOT, ir::registerSetSlot1_21_2);
ctx.clientbound(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT, ir::registerSetContent1_21_2);
ctx.clientbound(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
ctx.clientbound(ClientboundPackets1_21_2.COOLDOWN, ir::registerCooldown1_21_2);
ctx.serverbound(ServerboundPackets1_21_2.CONTAINER_CLICK, ir::registerContainerClick1_21_2);
ctx.serverbound(ServerboundPackets1_21_2.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
ctx.clientbound(ClientboundPackets1_21_2.SET_EQUIPMENT, ir::registerSetEquipment);
ctx.clientbound(ClientboundPackets1_21_2.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_21_2.MERCHANT_OFFERS, ir::registerMerchantOffers1_20_5);
ctx.clientbound(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY, ir::registerSetPlayerInventory, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, ir::registerSetCursorItem, PacketBound.ADDED_AT_MIN);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21_5(final RegistrationContext<CU, SU> ctx, final StructuredItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_21_5.CONTAINER_SET_SLOT, ir::registerSetSlot1_21_2);
ctx.clientbound(ClientboundPackets1_21_5.CONTAINER_SET_CONTENT, ir::registerSetContent1_21_2);
ctx.clientbound(ClientboundPackets1_21_5.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
ctx.clientbound(ClientboundPackets1_21_5.COOLDOWN, ir::registerCooldown1_21_2);
ctx.serverbound(ServerboundPackets1_21_5.CONTAINER_CLICK, ir::registerContainerClick1_21_5);
ctx.serverbound(ServerboundPackets1_21_5.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot1_21_5);
ctx.clientbound(ClientboundPackets1_21_5.SET_EQUIPMENT, ir::registerSetEquipment);
ctx.clientbound(ClientboundPackets1_21_5.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_21_5.MERCHANT_OFFERS, ir::registerMerchantOffers1_20_5);
ctx.clientbound(ClientboundPackets1_21_5.SET_PLAYER_INVENTORY, ir::registerSetPlayerInventory);
ctx.clientbound(ClientboundPackets1_21_5.SET_CURSOR_ITEM, ir::registerSetCursorItem);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21_6(final RegistrationContext<CU, SU> ctx, final StructuredItemRewriter<CU, SU, ?> ir) {
registerItemPackets1_21_5(ctx, ir);
ctx.clientbound(ClientboundPackets1_21_6.SHOW_DIALOG, ir::registerShowDialog, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundConfigurationPackets1_21_6.SHOW_DIALOG, ir::registerShowDialogDirect, PacketBound.ADDED_AT_MIN);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ItemRewriter<CU, SU, ?> item(final RegistrationContext<CU, SU> ctx) {
return ctx.protocol().getItemRewriter();
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> StructuredItemRewriter<CU, SU, ?> structuredItem(final RegistrationContext<CU, SU> ctx) {
return (StructuredItemRewriter<CU, SU, ?>) ctx.protocol().getItemRewriter();
}
}
@@ -0,0 +1,74 @@
/*
* 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.protocol.shared_registration.def;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
final class ParticleRegistrations {
static <CU extends ClientboundPacketType> void registerParticlePackets1_13(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_13.LEVEL_PARTICLES, type -> pr.registerLevelParticles1_13(type, Types.FLOAT));
}
static <CU extends ClientboundPacketType> void registerParticlePackets1_15_2(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_15.LEVEL_PARTICLES, type -> pr.registerLevelParticles1_13(type, Types.DOUBLE));
}
static <CU extends ClientboundPacketType> void registerParticlePackets1_19(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_19.LEVEL_PARTICLES, pr::registerLevelParticles1_19);
}
static <CU extends ClientboundPacketType> void registerParticlePackets1_20(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_19.LEVEL_PARTICLES, pr::registerLevelParticles1_19);
}
static <CU extends ClientboundPacketType> void registerParticlePackets1_20_5(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_20_5.LEVEL_PARTICLES, pr::registerLevelParticles1_20_5);
ctx.clientbound(ClientboundPackets1_20_5.EXPLODE, pr::registerExplode1_20_5);
}
static <CU extends ClientboundPacketType> void registerParticlePackets1_21_2(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_21_2.LEVEL_PARTICLES, pr::registerLevelParticles1_20_5);
ctx.clientbound(ClientboundPackets1_21_2.EXPLODE, pr::registerExplode1_21_2);
}
static <CU extends ClientboundPacketType> void registerParticlePackets1_21_4(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_21_2.LEVEL_PARTICLES, pr::registerLevelParticles1_21_4);
ctx.clientbound(ClientboundPackets1_21_2.EXPLODE, pr::registerExplode1_21_2);
}
static <CU extends ClientboundPacketType> void registerParticlePackets1_21_9(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_21_9.LEVEL_PARTICLES, pr::registerLevelParticles1_21_4);
ctx.clientbound(ClientboundPackets1_21_9.EXPLODE, pr::registerExplode1_21_9);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ParticleRewriter<CU> particle(final RegistrationContext<CU, SU> ctx) {
return ctx.protocol().getParticleRewriter();
}
}
@@ -0,0 +1,102 @@
/*
* 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.protocol.shared_registration.def;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.v1_17to1_17_1.packet.ClientboundPackets1_17_1;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.rewriter.CommandRewriter1_19_4;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundConfigurationPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
final class RegistryRegistrations {
static <CU extends ClientboundPacketType> void registerTags1_17_1(final RegistrationContext<CU, ?> ctx) {
if (ctx.protocol().getTagRewriter() == null) return;
ctx.clientbound(ClientboundPackets1_17_1.UPDATE_TAGS, ctx.protocol().getTagRewriter()::registerGeneric);
}
static <CU extends ClientboundPacketType> void registerTags1_20_2(final RegistrationContext<CU, ?> ctx) {
if (ctx.protocol().getTagRewriter() == null) return;
ctx.clientbound(ClientboundPackets1_20_2.UPDATE_TAGS, ctx.protocol().getTagRewriter()::registerGeneric);
ctx.clientbound(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, ctx.protocol().getTagRewriter()::registerGeneric, PacketBound.ADDED_AT_MIN);
}
static <CU extends ClientboundPacketType> void registerRegistryData1_21(final RegistrationContext<CU, ?> ctx) {
if (ctx.protocol().getRegistryDataRewriter() == null) return;
ctx.clientboundHandler(ClientboundConfigurationPackets1_21.REGISTRY_DATA, ctx.protocol().getRegistryDataRewriter()::handle);
}
static <CU extends ClientboundPacketType> void registerRecipePackets1_21_2(final RegistrationContext<CU, ?> ctx) {
final RecipeDisplayRewriter<CU> rr = ctx.protocol().getRecipeRewriter();
if (rr == null) return;
ctx.clientbound(ClientboundPackets1_21_2.UPDATE_RECIPES, rr::registerUpdateRecipes);
ctx.clientbound(ClientboundPackets1_21_2.RECIPE_BOOK_ADD, rr::registerRecipeBookAdd, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE, rr::registerPlaceGhostRecipe);
}
static <CU extends ClientboundPacketType> void registerStatistics1_13(final RegistrationContext<CU, ?> ctx) {
ctx.clientbound(ClientboundPackets1_13.AWARD_STATS, new StatisticsRewriter<>(ctx.protocol())::register);
}
static <CU extends ClientboundPacketType> void registerSounds1_10(final RegistrationContext<CU, ?> ctx) {
ctx.clientbound(ClientboundPackets1_9_3.SOUND, new SoundRewriter<>(ctx.protocol())::registerSound);
}
static <CU extends ClientboundPacketType> void registerSounds1_14(final RegistrationContext<CU, ?> ctx) {
final SoundRewriter<CU> sr = new SoundRewriter<>(ctx.protocol());
ctx.clientbound(ClientboundPackets1_14.SOUND, sr::registerSound);
ctx.clientbound(ClientboundPackets1_14.SOUND_ENTITY, sr::registerSound, PacketBound.ADDED_AT_MIN);
}
static <CU extends ClientboundPacketType> void registerSounds1_19_3(final RegistrationContext<CU, ?> ctx) {
final SoundRewriter<CU> sr = new SoundRewriter<>(ctx.protocol());
ctx.clientbound(ClientboundPackets1_19_3.SOUND, sr::registerSound1_19_3);
ctx.clientbound(ClientboundPackets1_19_3.SOUND_ENTITY, sr::registerSound1_19_3);
}
static <CU extends ClientboundPacketType> void registerCommands1_19(final RegistrationContext<CU, ?> ctx) {
if ((ctx.protocol().getMappingData() != null && !Mappings.isIntIdIdentity(ctx.protocol().getMappingData().getArgumentTypeMappings()))
|| ctx.protocol().getRegistryDataRewriter() != null) {
ctx.clientbound(ClientboundPackets1_19_3.COMMANDS, new CommandRewriter1_19_4<>(ctx.protocol())::registerDeclareCommands1_19);
}
}
static <CU extends ClientboundPacketType> void registerAttributes1_21(final RegistrationContext<CU, ?> ctx) {
ctx.clientbound(ClientboundPackets1_21.UPDATE_ATTRIBUTES, new AttributeRewriter<>(ctx.protocol())::register1_21);
}
}
@@ -0,0 +1,194 @@
/*
* 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.protocol.shared_registration.def;
import com.viaversion.viaversion.api.minecraft.item.data.ChatType;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2;
import com.viaversion.viaversion.protocols.v1_17to1_17_1.packet.ClientboundPackets1_17_1;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPackets1_19_1;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundConfigurationPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPackets1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPackets1_21_5;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.text.ComponentRewriterBase;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
final class TextComponentRegistrations {
static <CU extends ClientboundPacketType> void registerComponents1_12_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
ctx.clientbound(ClientboundPackets1_12_1.CHAT, cr::registerComponentPacket);
registerCombatAndTitle1_12_2(ctx, cr);
registerComponentsFrom1_12_2(ctx, cr);
}
static <CU extends ClientboundPacketType> void registerComponents1_14(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
ctx.clientbound(ClientboundPackets1_12_1.CHAT, cr::registerComponentPacket);
registerCombatAndTitle1_12_2(ctx, cr);
registerComponentsFrom1_12_2(ctx, cr);
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
}
static <CU extends ClientboundPacketType> void registerComponents1_16_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
ctx.clientbound(ClientboundPackets1_16.CHAT, cr::registerComponentPacket);
registerComponentsFrom1_12_2(ctx, cr);
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
if (!(cr instanceof final JsonNBTComponentRewriter<CU> jcr)) return;
ctx.clientbound(ClientboundPackets1_12_1.PLAYER_COMBAT, jcr::registerPlayerCombat, PacketBound.REMOVED_AT_MAX);
ctx.clientbound(ClientboundPackets1_12_1.SET_TITLES, jcr::registerTitle, PacketBound.REMOVED_AT_MAX);
}
static <CU extends ClientboundPacketType> void registerComponents1_17(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
ctx.clientbound(ClientboundPackets1_16.CHAT, cr::registerComponentPacket, PacketBound.REMOVED_AT_MAX);
registerComponentsFrom1_12_2(ctx, cr);
ctx.clientbound(ClientboundPackets1_17_1.SET_ACTION_BAR_TEXT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_17_1.SET_TITLE_TEXT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_17_1.SET_SUBTITLE_TEXT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
ctx.clientbound(ClientboundPackets1_17_1.PLAYER_COMBAT_KILL, jcr::registerPlayerCombatKill, PacketBound.ADDED_AT_MIN);
}
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
}
static <CU extends ClientboundPacketType> void registerComponents1_19(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
registerComponentsFrom1_12_2(ctx, cr);
registerActionBarTitleSubtitle1_17_1(ctx, cr);
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
ctx.clientbound(ClientboundPackets1_17_1.PLAYER_COMBAT_KILL, jcr::registerPlayerCombatKill);
}
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
ctx.clientbound(ClientboundPackets1_19.SYSTEM_CHAT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
ctx.clientbound(ClientboundPackets1_19.SERVER_DATA, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
}
static <CU extends ClientboundPacketType> void registerComponents1_20_3(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
registerComponentsFrom1_12_2(ctx, cr);
registerActionBarTitleSubtitle1_17_1(ctx, cr);
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
ctx.clientbound(ClientboundPackets1_19_1.SYSTEM_CHAT, cr::registerComponentPacket);
ctx.clientbound(ClientboundConfigurationPackets1_20_3.DISCONNECT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_3.DISGUISED_CHAT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_3.SET_SCORE, cr::registerSetScore1_20_3);
ctx.clientbound(ClientboundPackets1_20_3.PLAYER_COMBAT_KILL, cr::registerPlayerCombatKill1_20);
ctx.clientbound(ClientboundPackets1_20_5.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
ctx.clientbound(ClientboundPackets1_19.SERVER_DATA, cr::registerComponentPacket);
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
ctx.clientbound(ClientboundPackets1_20_3.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, Types.VAR_INT));
ctx.clientbound(ClientboundPackets1_20_3.PLAYER_INFO_UPDATE, jcr::registerPlayerInfoUpdate1_20_3);
}
}
static <CU extends ClientboundPacketType> void registerCombatAndTitle1_12_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
if (!(cr instanceof final JsonNBTComponentRewriter<CU> jcr)) return;
ctx.clientbound(ClientboundPackets1_12_1.PLAYER_COMBAT, jcr::registerPlayerCombat);
ctx.clientbound(ClientboundPackets1_12_1.SET_TITLES, jcr::registerTitle);
}
private static <CU extends ClientboundPacketType> void registerComponentsFrom1_12_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
// not including set_score, player_info, update_advancements, and open_screen
ctx.clientbound(ClientboundPackets1_12_1.BOSS_EVENT, cr::registerBossEvent);
ctx.clientbound(ClientboundPackets1_12_1.DISCONNECT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_12_1.TAB_LIST, cr::registerTabList);
cr.registerLoginDisconnect();
}
static <CU extends ClientboundPacketType> void registerActionBarTitleSubtitle1_17_1(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
ctx.clientbound(ClientboundPackets1_17_1.SET_ACTION_BAR_TEXT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_17_1.SET_TITLE_TEXT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_17_1.SET_SUBTITLE_TEXT, cr::registerComponentPacket);
}
static <CU extends ClientboundPacketType> void registerComponents1_20_5(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
common1_20_5(ctx, cr);
ctx.clientbound(ClientboundPackets1_20_5.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
ctx.clientbound(ClientboundPackets1_20_5.DISGUISED_CHAT, cr::registerComponentPacket);
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, Types.VAR_INT));
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_INFO_UPDATE, jcr::registerPlayerInfoUpdate1_20_3);
}
}
private static <CU extends ClientboundPacketType> void common1_20_5(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
ctx.clientbound(ClientboundConfigurationPackets1_20_5.DISCONNECT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_5.DISCONNECT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_5.SET_ACTION_BAR_TEXT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_5.SET_TITLE_TEXT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_5.SET_SUBTITLE_TEXT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_5.BOSS_EVENT, cr::registerBossEvent);
ctx.clientbound(ClientboundPackets1_20_5.TAB_LIST, cr::registerTabList);
ctx.clientbound(ClientboundPackets1_20_5.SET_OBJECTIVE, cr::registerSetObjective);
ctx.clientbound(ClientboundPackets1_20_5.SET_SCORE, cr::registerSetScore1_20_3);
ctx.clientbound(ClientboundPackets1_20_5.SYSTEM_CHAT, cr::registerComponentPacket);
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_COMBAT_KILL, cr::registerPlayerCombatKill1_20);
ctx.clientbound(ClientboundPackets1_20_5.SERVER_DATA, cr::registerComponentPacket);
cr.registerLoginDisconnect();
}
static <CU extends ClientboundPacketType> void registerComponents1_21(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
common1_20_5(ctx, cr);
ctx.clientbound(ClientboundPackets1_21.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
ctx.clientbound(ClientboundPackets1_21.DISGUISED_CHAT, cr::registerDisguisedChat);
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
ctx.clientbound(ClientboundPackets1_21.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, ChatType.TYPE));
ctx.clientbound(ClientboundPackets1_21.PLAYER_INFO_UPDATE, jcr::registerPlayerInfoUpdate1_20_3);
}
}
static <CU extends ClientboundPacketType> void registerComponents1_21_4(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
common1_20_5(ctx, cr);
ctx.clientbound(ClientboundPackets1_21_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
ctx.clientbound(ClientboundPackets1_21_2.DISGUISED_CHAT, cr::registerDisguisedChat);
ctx.clientbound(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE, cr::registerPlayerInfoUpdate1_21_4);
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
ctx.clientbound(ClientboundPackets1_21_2.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, ChatType.TYPE));
}
}
static <CU extends ClientboundPacketType> void registerComponents1_21_5(final RegistrationContext<CU, ?> ctx, final NBTComponentRewriter<CU> cr) {
common1_20_5(ctx, cr);
ctx.clientbound(ClientboundPackets1_21_5.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_21_5);
ctx.clientbound(ClientboundPackets1_21_5.DISGUISED_CHAT, cr::registerDisguisedChat);
ctx.clientbound(ClientboundPackets1_21_5.PLAYER_INFO_UPDATE, cr::registerPlayerInfoUpdate1_21_4);
ctx.clientbound(ClientboundPackets1_21_5.PLAYER_CHAT, cr::registerPlayerChat1_21_5);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ComponentRewriterBase<CU> text(final RegistrationContext<CU, SU> ctx) {
return ctx.protocol().getComponentRewriter();
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> NBTComponentRewriter<CU> nbtText(final RegistrationContext<CU, SU> ctx) {
return (NBTComponentRewriter<CU>) ctx.protocol().getComponentRewriter();
}
}
@@ -1,109 +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.protocols.template;
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.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.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
// RecipeDisplayRewriter
// Types1_21_4, Types1_OLD
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21_6, ServerboundPacket1_21_6, Protocol1_98To1_99> {
public BlockItemPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
// 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);
// 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);
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);
// 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
}
@Override
protected void backupInconvertibleData(final UserConnection connection, final Item item, final StructuredDataContainer dataContainer, final CompoundTag backupTag) {
super.backupInconvertibleData(connection, item, dataContainer, backupTag);
// back up any data if needed here, called before the method below
}
@Override
protected void handleItemDataComponentsToClient(final UserConnection connection, final Item item, final StructuredDataContainer container) {
upgradeData(item, container);
super.handleItemDataComponentsToClient(connection, item, container);
}
public static void upgradeData(final Item item, final StructuredDataContainer container) { // public for VB
}
@Override
protected void handleItemDataComponentsToServer(final UserConnection connection, final Item item, final StructuredDataContainer container) {
downgradeData(item, container);
super.handleItemDataComponentsToServer(connection, item, container);
}
public static void downgradeData(final Item item, final StructuredDataContainer container) {
}
@Override
protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) {
super.restoreBackupData(item, container, customData);
// restore any data if needed here
}
}
@@ -0,0 +1,73 @@
/*
* 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.protocols.template;
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.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
// To replace if needed:
// RecipeDisplayRewriter
final class BlockItemPacketRewriter99_1 extends StructuredItemRewriter<ClientboundPacket26_1, ServerboundPacket1_21_9, Protocol98_1To99_1> {
public BlockItemPacketRewriter99_1(final Protocol98_1To99_1 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
// Common block, item, recipe, and entity registrations are handled by SharedRegistrations
// registerOpenScreen(ClientboundPackets26_1.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
// OR add new serializers to RecipeDisplayRewriter, or extend the last one for changes
}
@Override
protected void backupInconvertibleData(final UserConnection connection, final Item item, final StructuredDataContainer dataContainer, final CompoundTag backupTag) {
super.backupInconvertibleData(connection, item, dataContainer, backupTag);
// back up any data if needed here, called before the method below
}
@Override
protected void handleItemDataComponentsToClient(final UserConnection connection, final Item item, final StructuredDataContainer container) {
upgradeData(item, container);
super.handleItemDataComponentsToClient(connection, item, container);
}
public static void upgradeData(final Item item, final StructuredDataContainer container) { // public for VB
}
@Override
protected void handleItemDataComponentsToServer(final UserConnection connection, final Item item, final StructuredDataContainer container) {
downgradeData(item, container);
super.handleItemDataComponentsToServer(connection, item, container);
}
public static void downgradeData(final Item item, final StructuredDataContainer container) {
}
@Override
protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) {
super.restoreBackupData(item, container, customData);
// restore any data if needed here
}
}
@@ -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,29 @@
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.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);
// Common entity registrations (SET_ENTITY_DATA, REMOVE_ENTITIES, PLAYER_ABILITIES,
// GAME_EVENT, LOGIN, RESPAWN) are handled by SharedRegistrations.
}
@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 -> {
@@ -70,14 +63,8 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
);
}
@Override
public void onMappingDataLoaded() {
// IF ENTITY TYPES CHANGED: Automatically map entity id changes AFTER entity ids have been loaded
mapTypes();
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_9.getTypeFromId(type);
return EntityTypes1_21_11.getTypeFromId(type);
}
}
@@ -20,92 +20,62 @@ 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.protocol.AbstractProtocol;
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.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
import com.viaversion.viaversion.api.type.types.version.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.api.protocol.AbstractProtocol;
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.rewriter.AttributeRewriter;
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.BlockRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.block.BlockRewriter1_21_5;
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
// ChunkType26_1::new
// 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 BlockRewriter<ClientboundPacket26_1> blockRewriter = new BlockRewriter1_21_5<>(this, ChunkType26_1::new);
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);
tagRewriter.registerGeneric(ClientboundPackets1_21_6.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_6.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.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
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);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_6.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_6.UPDATE_ATTRIBUTES);
// Common registrations (tags, components, particles, sounds, statistics, attributes)
// are automatically applied via SharedRegistrations based on the protocol's version range.
// Only protocol-specific registrations need to be added here.
// 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 +88,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 +115,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 +123,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,52 +135,57 @@ 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;
}
@Override
public BlockRewriter<ClientboundPacket26_1> getBlockRewriter() {
return blockRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@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)
);
}
}
@@ -37,7 +37,6 @@ import com.viaversion.viaversion.protocols.v1_10to1_11.rewriter.ItemPacketRewrit
import com.viaversion.viaversion.protocols.v1_10to1_11.storage.EntityTracker1_11;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
import com.viaversion.viaversion.rewriter.SoundRewriter;
public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3, ClientboundPackets1_9_3, ServerboundPackets1_9_3, ServerboundPackets1_9_3> {
@@ -59,7 +58,15 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
protected void registerPackets() {
super.registerPackets();
new SoundRewriter<>(this, this::getNewSoundId).registerSound(ClientboundPackets1_9_3.SOUND);
registerClientbound(ClientboundPackets1_9_3.SOUND, wrapper -> {
int soundId = wrapper.read(Types.VAR_INT);
int mappedId = getNewSoundId(soundId);
if (mappedId == -1) {
wrapper.cancel();
} else {
wrapper.write(Types.VAR_INT, mappedId);
}
});
registerClientbound(ClientboundPackets1_9_3.SET_TITLES, new PacketHandlers() {
@Override
@@ -43,7 +43,6 @@ import com.viaversion.viaversion.protocols.v1_11_1to1_12.rewriter.EntityPacketRe
import com.viaversion.viaversion.protocols.v1_11_1to1_12.rewriter.ItemPacketRewriter1_12;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
import com.viaversion.viaversion.rewriter.SoundRewriter;
public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9_3, ClientboundPackets1_12, ServerboundPackets1_9_3, ServerboundPackets1_12> {
@@ -58,6 +57,16 @@ public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundPackets1_9_3.SOUND, wrapper -> {
int soundId = wrapper.read(Types.VAR_INT);
int mappedId = getNewSoundId(soundId);
if (mappedId == -1) {
wrapper.cancel();
} else {
wrapper.write(Types.VAR_INT, mappedId);
}
});
registerClientbound(ClientboundPackets1_9_3.CHAT, wrapper -> {
final JsonElement element = wrapper.passthrough(Types.COMPONENT);
TranslateRewriter.toClient(wrapper.user(), element);
@@ -96,9 +105,6 @@ public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9
}
});
new SoundRewriter<>(this, this::getNewSoundId).registerSound(ClientboundPackets1_9_3.SOUND);
// New packet at 0x01
cancelServerbound(ServerboundPackets1_12.CRAFTING_RECIPE_PLACEMENT);
@@ -40,7 +40,6 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.protocols.base.ClientboundStatusPackets;
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.ConnectionData;
@@ -181,10 +180,6 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
WorldPacketRewriter1_13.register(this);
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_DISCONNECT, wrapper -> {
componentRewriter.processText(wrapper.user(), wrapper.passthrough(Types.COMPONENT));
});
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE, new PacketHandlers() {
@Override
public void register() {
@@ -253,9 +248,6 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
});
componentRewriter.registerBossEvent(ClientboundPackets1_12_1.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets1_12_1.CHAT);
registerClientbound(ClientboundPackets1_12_1.COMMAND_SUGGESTIONS, wrapper -> {
wrapper.write(Types.VAR_INT, wrapper.user().get(TabCompleteTracker.class).getTransactionId());
@@ -329,8 +321,6 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
}
});
componentRewriter.registerComponentPacket(ClientboundPackets1_12_1.DISCONNECT);
registerClientbound(ClientboundPackets1_12_1.LEVEL_EVENT, new PacketHandlers() {
@Override
public void register() {
@@ -359,8 +349,6 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
}
});
componentRewriter.registerPlayerCombat(ClientboundPackets1_12_1.PLAYER_COMBAT);
registerClientbound(ClientboundPackets1_12_1.MAP_ITEM_DATA, new PacketHandlers() {
@Override
public void register() {
@@ -510,17 +498,6 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
}
});
componentRewriter.registerTitle(ClientboundPackets1_12_1.SET_TITLES);
// New 0x4C - Stop Sound
new SoundRewriter<>(this).registerSound(ClientboundPackets1_12_1.SOUND);
registerClientbound(ClientboundPackets1_12_1.TAB_LIST, wrapper -> {
componentRewriter.processText(wrapper.user(), wrapper.passthrough(Types.COMPONENT));
componentRewriter.processText(wrapper.user(), wrapper.passthrough(Types.COMPONENT));
});
registerClientbound(ClientboundPackets1_12_1.UPDATE_ADVANCEMENTS, wrapper -> {
wrapper.passthrough(Types.BOOLEAN); // Reset/clear
int size = wrapper.passthrough(Types.VAR_INT); // Mapping size
@@ -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,7 +23,6 @@ import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_14;
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.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.Types1_13_2;
import com.viaversion.viaversion.api.type.types.version.Types1_14;
@@ -38,10 +37,9 @@ import com.viaversion.viaversion.protocols.v1_13_2to1_14.rewriter.ItemPacketRewr
import com.viaversion.viaversion.protocols.v1_13_2to1_14.rewriter.PlayerPacketRewriter1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.rewriter.WorldPacketRewriter1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.storage.EntityTracker1_14;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.CommandRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.ProtocolLogger;
@@ -55,6 +53,7 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
private final ItemPacketRewriter1_14 itemRewriter = new ItemPacketRewriter1_14(this);
private final ParticleRewriter<ClientboundPackets1_13> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPackets1_13> tagRewriter = new TagRewriter<>(this);
private final BlockRewriter<ClientboundPackets1_13> blockRewriter = BlockRewriter.for1_14(this);
public Protocol1_13_2To1_14() {
super(ClientboundPackets1_13.class, ClientboundPackets1_14.class, ServerboundPackets1_13.class, ServerboundPackets1_14.class);
@@ -67,11 +66,6 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
WorldPacketRewriter1_14.register(this);
PlayerPacketRewriter1_14.register(this);
new SoundRewriter<>(this).registerSound(ClientboundPackets1_13.SOUND);
new StatisticsRewriter<>(this).register(ClientboundPackets1_13.AWARD_STATS);
particleRewriter.registerLevelParticles1_13(ClientboundPackets1_13.LEVEL_PARTICLES, Types.FLOAT);
JsonNBTComponentRewriter<ClientboundPackets1_13> componentRewriter = new ComponentRewriter1_14<>(this);
componentRewriter.registerComponentPacket(ClientboundPackets1_13.CHAT);
@@ -109,16 +103,8 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
WorldPacketRewriter1_14.caveAir = MAPPINGS.getBlockStateMappings().getNewId(8592);
EntityTypes1_14.initialize(this);
Types1_13_2.PARTICLE.filler(this, false)
.reader("block", ParticleType.Readers.BLOCK)
.reader("dust", ParticleType.Readers.DUST)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("item", ParticleType.Readers.ITEM1_13_2);
Types1_14.PARTICLE.filler(this)
.reader("block", ParticleType.Readers.BLOCK)
.reader("dust", ParticleType.Readers.DUST)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("item", ParticleType.Readers.ITEM1_13_2);
ParticleType.Fillers.fill1_13_2(this, Types1_13_2.PARTICLE, false);
ParticleType.Fillers.fill1_13_2(this, Types1_14.PARTICLE, true);
tagRewriter.addEmptyTag(RegistryType.BLOCK, "bamboo_plantable_on");
@@ -151,6 +137,11 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
return itemRewriter;
}
@Override
public BlockRewriter<ClientboundPackets1_13> getBlockRewriter() {
return blockRewriter;
}
@Override
public ParticleRewriter<ClientboundPackets1_13> getParticleRewriter() {
return particleRewriter;
@@ -252,7 +252,6 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
}
});
registerRemoveEntities(ClientboundPackets1_13.REMOVE_ENTITIES);
registerSetEntityData(ClientboundPackets1_13.SET_ENTITY_DATA, Types1_13_2.ENTITY_DATA_LIST, Types1_14.ENTITY_DATA_LIST);
}
@@ -386,7 +385,7 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
@Override
public void onMappingDataLoaded() {
mapTypes();
super.onMappingDataLoaded();
if (Via.getConfig().translateOcelotToCat()) {
// A better solution for this would be to despawn the ocelot and spawn a cat in its place, but that would
// require a lot of data tracking and is not worth the effort.
@@ -64,9 +64,6 @@ public class ItemPacketRewriter1_14 extends ItemRewriter<ClientboundPackets1_13,
@Override
public void registerPackets() {
registerCooldown(ClientboundPackets1_13.COOLDOWN);
registerAdvancements(ClientboundPackets1_13.UPDATE_ADVANCEMENTS);
protocol.registerClientbound(ClientboundPackets1_13.OPEN_SCREEN, null, wrapper -> {
Short windowId = wrapper.read(Types.UNSIGNED_BYTE);
String type = wrapper.read(Types.STRING);
@@ -112,9 +109,6 @@ public class ItemPacketRewriter1_14 extends ItemRewriter<ClientboundPackets1_13,
}
});
registerSetContent(ClientboundPackets1_13.CONTAINER_SET_CONTENT);
registerSetSlot(ClientboundPackets1_13.CONTAINER_SET_SLOT);
protocol.registerClientbound(ClientboundPackets1_13.CUSTOM_PAYLOAD, new PacketHandlers() {
@Override
public void register() {
@@ -166,8 +160,6 @@ public class ItemPacketRewriter1_14 extends ItemRewriter<ClientboundPackets1_13,
}
});
registerSetEquippedItem(ClientboundPackets1_13.SET_EQUIPPED_ITEM);
RecipeRewriter<ClientboundPackets1_13> recipeRewriter = new RecipeRewriter<>(protocol);
protocol.registerClientbound(ClientboundPackets1_13.UPDATE_RECIPES, wrapper -> {
int size = wrapper.passthrough(Types.VAR_INT);
@@ -188,8 +180,6 @@ public class ItemPacketRewriter1_14 extends ItemRewriter<ClientboundPackets1_13,
});
registerContainerClick(ServerboundPackets1_14.CONTAINER_CLICK);
protocol.registerServerbound(ServerboundPackets1_14.SELECT_TRADE, wrapper -> {
// Selecting trade now moves the items, we need to resync the inventory
PacketWrapper resyncPacket = wrapper.create(ServerboundPackets1_13.CONTAINER_CLICK);
@@ -204,8 +194,6 @@ public class ItemPacketRewriter1_14 extends ItemRewriter<ClientboundPackets1_13,
resyncPacket.write(Types.ITEM1_13_2, new DataItem(1, (byte) 1, tag)); // 5 - Clicked Item
resyncPacket.scheduleSendToServer(Protocol1_13_2To1_14.class);
});
registerSetCreativeModeSlot(ServerboundPackets1_14.SET_CREATIVE_MODE_SLOT);
}
@Override
@@ -37,7 +37,6 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPacke
import com.viaversion.viaversion.protocols.v1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.storage.EntityTracker1_14;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.util.CompactArrayUtil;
import java.util.Arrays;
@@ -53,8 +52,6 @@ public class WorldPacketRewriter1_14 {
}
public static void register(Protocol1_13_2To1_14 protocol) {
BlockRewriter<ClientboundPackets1_13> blockRewriter = BlockRewriter.for1_14(protocol);
protocol.registerClientbound(ClientboundPackets1_13.BLOCK_DESTRUCTION, new PacketHandlers() {
@Override
public void register() {
@@ -69,7 +66,7 @@ public class WorldPacketRewriter1_14 {
map(Types.BLOCK_POSITION1_8, Types.BLOCK_POSITION1_14);
}
});
protocol.registerClientbound(ClientboundPackets1_13.BLOCK_EVENT, new PacketHandlers() {
protocol.replaceClientbound(ClientboundPackets1_13.BLOCK_EVENT, new PacketHandlers() {
@Override
public void register() {
map(Types.BLOCK_POSITION1_8, Types.BLOCK_POSITION1_14); // Location
@@ -79,7 +76,7 @@ public class WorldPacketRewriter1_14 {
handler(wrapper -> wrapper.set(Types.VAR_INT, 0, protocol.getMappingData().getNewBlockId(wrapper.get(Types.VAR_INT, 0))));
}
});
protocol.registerClientbound(ClientboundPackets1_13.BLOCK_UPDATE, new PacketHandlers() {
protocol.replaceClientbound(ClientboundPackets1_13.BLOCK_UPDATE, new PacketHandlers() {
@Override
public void register() {
map(Types.BLOCK_POSITION1_8, Types.BLOCK_POSITION1_14);
@@ -102,8 +99,6 @@ public class WorldPacketRewriter1_14 {
}
});
blockRewriter.registerChunkBlocksUpdate(ClientboundPackets1_13.CHUNK_BLOCKS_UPDATE);
protocol.registerClientbound(ClientboundPackets1_13.EXPLODE, new PacketHandlers() {
@Override
public void register() {
@@ -247,7 +242,7 @@ public class WorldPacketRewriter1_14 {
}
});
protocol.registerClientbound(ClientboundPackets1_13.LEVEL_EVENT, new PacketHandlers() {
protocol.replaceClientbound(ClientboundPackets1_13.LEVEL_EVENT, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // Effect Id
Loaded 100 of 237 files, more files were not shown because too many files have changed in this diff. Show more