Compare commits

..
47 Commits
Author SHA1 Message Date
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
109 changed files with 2285 additions and 283 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
--------
@@ -170,6 +170,8 @@ public interface MappingData {
@Nullable FullMappings getRecipeSerializerMappings();
@Nullable FullMappings getSlotDisplayMappings();
@Nullable FullMappings getDataComponentSerializerMappings();
default @Nullable FullMappings getFullMappings(final MappingType mappingType) {
@@ -45,6 +45,7 @@ public class MappingDataBase implements MappingData {
protected FullMappings entityMappings;
protected FullMappings recipeSerializerMappings;
protected FullMappings itemDataSerializerMappings;
protected FullMappings slotDisplayMappings;
protected FullMappings attributeMappings;
protected FullMappings blockEntityMappings;
protected ParticleMappings particleMappings;
@@ -89,6 +90,7 @@ public class MappingDataBase implements MappingData {
entityMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "entities");
argumentTypeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "argumenttypes");
slotDisplayMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "slot_displays");
recipeSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "recipe_serializers");
itemDataSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "data_component_type");
attributeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "attributes");
@@ -335,6 +337,11 @@ public class MappingDataBase implements MappingData {
return recipeSerializerMappings;
}
@Override
public @Nullable FullMappings getSlotDisplayMappings() {
return slotDisplayMappings;
}
@Override
public @Nullable IntSet changedBlocks() {
return changedBlocks;
@@ -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());
}
}
@@ -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,41 @@
/*
* 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.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
public record ProvidesBannerPatterns(HolderSet patterns) {
public static final Type<ProvidesBannerPatterns> TYPE = new TransformingType<>(Types.HOLDER_SET, ProvidesBannerPatterns.class, ProvidesBannerPatterns::new, ProvidesBannerPatterns::patterns) {
@Override
public void write(final Ops ops, final ProvidesBannerPatterns value) {
ops.writeMap(map -> map.write("items", new HolderSetType(RegistryKey.of("banner_pattern")), value.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#sendPlayerDetails()} is true.
*
* @param connection The UserConnection
* @param payload The constructed payload to modify
*/
default void modifyServerDetails(UserConnection connection, JsonObject payload) {
// To be overridden if needed
}
/**
* Send a custom payload to from a player to the server.
*
@@ -328,6 +328,13 @@ public interface PacketWrapper {
*/
void resetReader();
/**
* Rewind the reader by the given number of arguments, so they can be read again.
*
* @param values number of values to add to the reader dequeue again
*/
void rewindReader(int values);
/**
* Sends this packet to the server.
* <b>Unlike {@link #sendToServer(Class)}, this method does not handle the pipeline with packet id and data changes.</b>
@@ -382,12 +389,21 @@ public interface PacketWrapper {
*/
void scheduleSendToServer(Class<? extends Protocol> protocol, boolean skipCurrentPipeline) throws InformativeException;
/**
* Allows running through code that may both read and write data to/from this packet wrapper,
* but will no-op any write call.
*
* @param runnable runnable to do further method calls on this packet wrapper
*/
void consumeReadsOnly(Runnable runnable);
/**
* Returns the packet type, or null if not transformed or manually unset.
*
* @return packet type if set
*/
@Nullable PacketType getPacketType();
@Nullable
PacketType getPacketType();
/**
* Sets the packet type. If set to null, it will not be written to the buffer with {@link #writeToBuffer(ByteBuf)}.
@@ -93,6 +93,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_21_7 = register(772, "1.21.7-1.21.8", new SubVersionRange("1.21", 7, 8));
public static final ProtocolVersion v1_21_9 = register(773, "1.21.9-1.21.10", new SubVersionRange("1.21", 9, 10));
public static final ProtocolVersion v1_21_11 = register(774, "1.21.11");
public static final ProtocolVersion v26_1 = register(775, "26.1");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -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.
*
@@ -27,5 +27,8 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public interface RegistryDataRewriter {
@Nullable KeyMappings getMappings(String registryKey);
@Nullable
KeyMappings getMappings(String registryKey);
boolean shouldRemoveRegistry(String registryKey);
}
@@ -103,7 +103,7 @@ 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;
@@ -198,7 +198,9 @@ 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();
@@ -28,13 +28,21 @@ import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public class VarIntArrayType extends Type<int[]> {
public VarIntArrayType() {
private final int length;
public VarIntArrayType(final int length) {
super(int[].class);
this.length = length;
}
public VarIntArrayType() {
this(-1);
}
@Override
public int[] read(ByteBuf buffer) {
int length = Types.VAR_INT.readPrimitive(buffer);
int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length)); // Sanity check, at least 1 byte will be used for each varint
int[] array = new int[length];
for (int i = 0; i < array.length; i++) {
@@ -45,7 +53,11 @@ public class VarIntArrayType extends Type<int[]> {
@Override
public void write(ByteBuf buffer, int[] object) {
Types.VAR_INT.writePrimitive(buffer, object.length);
if (this.length != -1) {
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
} else {
Types.VAR_INT.writePrimitive(buffer, object.length);
}
for (int i : object) {
Types.VAR_INT.writePrimitive(buffer, i);
}
@@ -31,8 +31,8 @@ import io.netty.buffer.ByteBuf;
public class ChunkSectionType1_18 extends Type<ChunkSection> {
private final PaletteTypeBase blockPaletteType;
private final PaletteTypeBase biomePaletteType;
protected final PaletteTypeBase blockPaletteType;
protected final PaletteTypeBase biomePaletteType;
public ChunkSectionType1_18(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(ChunkSection.class);
@@ -0,0 +1,68 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import io.netty.buffer.ByteBuf;
public class ChunkSectionType26_1 extends ChunkSectionType1_18 {
public ChunkSectionType26_1(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(
new PaletteType1_21_5(PaletteType.BLOCKS, globalPaletteBlockBits),
new PaletteType1_21_5(PaletteType.BIOMES, globalPaletteBiomeBits)
);
}
@Override
public ChunkSection read(final ByteBuf buffer) {
final ChunkSection chunkSection = new ChunkSectionImpl();
chunkSection.setNonAirBlocksCount(buffer.readShort());
chunkSection.setFluidCount(buffer.readShort());
chunkSection.addPalette(PaletteType.BLOCKS, blockPaletteType.read(buffer));
chunkSection.addPalette(PaletteType.BIOMES, biomePaletteType.read(buffer));
return chunkSection;
}
@Override
public void write(final ByteBuf buffer, final ChunkSection section) {
buffer.writeShort(section.getNonAirBlocksCount());
buffer.writeShort(section.getFluidCount());
blockPaletteType.write(buffer, section.palette(PaletteType.BLOCKS));
biomePaletteType.write(buffer, section.palette(PaletteType.BIOMES));
}
@Override
public int serializedSize(final Chunk chunk) {
int length = 0;
for (final ChunkSection section : chunk.getSections()) {
length += Short.BYTES + Short.BYTES // non-air and fluid count
+ blockPaletteType.serializedSize(section.palette(PaletteType.BLOCKS))
+ biomePaletteType.serializedSize(section.palette(PaletteType.BIOMES));
}
return length;
}
}
@@ -34,14 +34,18 @@ import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class ChunkType1_21_5 extends Type<Chunk> {
public class ChunkType1_21_5 extends Type<Chunk> {
private final ChunkSectionType1_18 sectionType;
private final int ySectionCount;
public ChunkType1_21_5(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
this(new ChunkSectionType1_21_5(globalPaletteBlockBits, globalPaletteBiomeBits), ySectionCount);
}
protected ChunkType1_21_5(final ChunkSectionType1_18 sectionType, final int ySectionCount) {
super(Chunk.class);
Preconditions.checkArgument(ySectionCount > 0);
this.sectionType = new ChunkSectionType1_21_5(globalPaletteBlockBits, globalPaletteBiomeBits);
this.sectionType = sectionType;
this.ySectionCount = ySectionCount;
}
@@ -0,0 +1,30 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
public final class ChunkType26_1 extends ChunkType1_21_5 {
public ChunkType26_1(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(new ChunkSectionType26_1(globalPaletteBlockBits, globalPaletteBiomeBits), ySectionCount);
}
}
@@ -0,0 +1,64 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.item;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.StructuredItemTemplate;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.util.Map;
// Holds the same exact data as a regular item stack
public class ItemTemplateType26_1 extends ItemType1_20_5 {
public ItemTemplateType26_1(final StructuredDataTypeBase dataType) {
super(dataType);
}
@Override
public Item read(final ByteBuf buffer) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final int amount = Types.VAR_INT.readPrimitive(buffer);
final Map<StructuredDataKey<?>, StructuredData<?>> data = readData(buffer);
return new StructuredItemTemplate(id, amount, new StructuredDataContainer(data));
}
@Override
public void write(final ByteBuf buffer, final Item object) {
Types.VAR_INT.writePrimitive(buffer, object.identifier());
Types.VAR_INT.writePrimitive(buffer, object.amount());
writeData(buffer, object);
}
public static final class OptionalItemTemplateType extends OptionalType<Item> {
public OptionalItemTemplateType(final Type<Item> type) {
super(type);
}
}
}
@@ -58,7 +58,7 @@ public class ItemType1_20_5 extends Type<Item> {
return new StructuredItem(id, amount, new StructuredDataContainer(data));
}
private Map<StructuredDataKey<?>, StructuredData<?>> readData(final ByteBuf buffer) {
protected Map<StructuredDataKey<?>, StructuredData<?>> readData(final ByteBuf buffer) {
final int valuesSize = Types.VAR_INT.readPrimitive(buffer);
final int markersSize = Types.VAR_INT.readPrimitive(buffer);
if (valuesSize == 0 && markersSize == 0) {
@@ -92,6 +92,10 @@ public class ItemType1_20_5 extends Type<Item> {
Types.VAR_INT.writePrimitive(buffer, object.amount());
Types.VAR_INT.writePrimitive(buffer, object.identifier());
writeData(buffer, object);
}
protected void writeData(final ByteBuf buffer, final Item object) {
final Map<StructuredDataKey<?>, StructuredData<?>> data = object.dataContainer().data();
int valuesSize = 0;
int markersSize = 0;
@@ -29,7 +29,7 @@ import com.viaversion.viaversion.api.type.types.UnsignedIntType;
import com.viaversion.viaversion.util.MathUtil;
import io.netty.buffer.ByteBuf;
public class MovementVectorType extends Type<Vector3d> {
public class LowPrecisionVectorType extends Type<Vector3d> {
// Using 15 bits, steal short constants for it
private static final double MAX_QUANTIZED_VALUE = Short.MAX_VALUE - 1;
private static final int SCALE_BITS = 2; // first 2 bits for the scale
@@ -38,7 +38,7 @@ public class MovementVectorType extends Type<Vector3d> {
private static final double ABS_MAX_VALUE = (1L << Integer.SIZE + SCALE_BITS) - 1; // Unsigned int + the first two scale bits
private static final double ABS_MIN_VALUE = 1 / MAX_QUANTIZED_VALUE;
public MovementVectorType() {
public LowPrecisionVectorType() {
super(Vector3d.class);
}
@@ -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
@@ -50,7 +50,7 @@ public class Types1_20_5<K extends VersionedStructuredDataKeys, E extends Abstra
public final Type<Item[]> itemArray = new ArrayType<>(item);
public final Type<Item> itemCost = new ItemCostType1_20_5(structuredDataArray);
public final Type<Item> optionalItemCost = new ItemCostType1_20_5.OptionalItemCostType(itemCost);
public final K structuredDataKeys;
private K structuredDataKeys;
public final ParticleType particle = new ParticleType();
public final ArrayType<Particle> particles = new ArrayType<>(particle);
@@ -58,11 +58,17 @@ public class Types1_20_5<K extends VersionedStructuredDataKeys, E extends Abstra
public final Type<EntityData> entityData;
public final Type<List<EntityData>> entityDataList;
public Types1_20_5(final Function<Types1_20_5<?, ?>, K> keysSupplier, final Function<Types1_20_5<?, ?>, E> entityDataTypesSupplier) {
this.structuredDataKeys = keysSupplier.apply(this);
public Types1_20_5(final Function<VersionedTypesHolder, K> keysSupplier, final Function<VersionedTypesHolder, E> entityDataTypesSupplier) {
this.entityDataTypes = entityDataTypesSupplier.apply(this);
this.entityData = new EntityDataType(entityDataTypes);
this.entityDataList = new EntityDataListType(entityData);
if (keysSupplier != null) {
initKeys(keysSupplier);
}
}
protected void initKeys(final Function<VersionedTypesHolder, K> keysSupplier) {
this.structuredDataKeys = keysSupplier.apply(this);
}
@Override
@@ -75,6 +81,21 @@ public class Types1_20_5<K extends VersionedStructuredDataKeys, E extends Abstra
return itemArray;
}
@Override
public Type<Item> itemTemplate() {
return item;
}
@Override
public Type<Item> optionalItemTemplate() {
return item;
}
@Override
public Type<Item[]> itemTemplateArray() {
return itemArray;
}
@Override
public Type<Item> itemCost() {
return itemCost;
@@ -34,7 +34,7 @@ public final class Types1_21 extends Types1_20_5<StructuredDataKeys1_20_5, Entit
public final Type<Item> optionalItem; // Optional as in boolean prefixed, not via the amount
public Types1_21(final Function<Types1_20_5<?, ?>, StructuredDataKeys1_20_5> keysSupplier, final Function<Types1_20_5<?, ?>, EntityDataTypes1_21> entityDataTypesSupplier) {
public Types1_21(final Function<VersionedTypesHolder, StructuredDataKeys1_20_5> keysSupplier, final Function<VersionedTypesHolder, EntityDataTypes1_21> entityDataTypesSupplier) {
super(keysSupplier, entityDataTypesSupplier);
this.optionalItem = ((ItemType1_20_5) item).new OptionalItemType();
}
@@ -0,0 +1,58 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.data.version.VersionedStructuredDataKeys;
import com.viaversion.viaversion.api.minecraft.entitydata.types.AbstractEntityDataTypes;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.item.ItemTemplateType26_1;
import java.util.function.Function;
public class Types26_1<K extends VersionedStructuredDataKeys, E extends AbstractEntityDataTypes> extends Types1_20_5<K, E> {
public final Type<Item> itemTemplate = new ItemTemplateType26_1(structuredData);
public final Type<Item> optionalItemTemplate = new ItemTemplateType26_1.OptionalItemTemplateType(itemTemplate);
public final Type<Item[]> itemTemplateArray = new ArrayType<>(itemTemplate);
public Types26_1(final Function<VersionedTypesHolder, K> keysSupplier, final Function<VersionedTypesHolder, E> entityDataTypesSupplier) {
super(null, entityDataTypesSupplier);
initKeys(keysSupplier);
}
@Override
public Type<Item> itemTemplate() {
return itemTemplate;
}
@Override
public Type<Item> optionalItemTemplate() {
return optionalItemTemplate;
}
@Override
public Type<Item[]> itemTemplateArray() {
return itemTemplateArray;
}
}
@@ -32,6 +32,7 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_2;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
/**
* Holds versioned accessors for highly volatile types, specifically around items and data components.
@@ -49,4 +50,5 @@ public final class VersionedTypes {
public static final Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_5> V1_21_6 = new Types1_20_5<>(StructuredDataKeys1_21_5::new, EntityDataTypes1_21_5::new);
public static final Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_9> V1_21_9 = new Types1_20_5<>(StructuredDataKeys1_21_5::new, EntityDataTypes1_21_9::new);
public static final Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes1_21_11> V1_21_11 = new Types1_20_5<>(StructuredDataKeys1_21_11::new, EntityDataTypes1_21_11::new);
public static final Types26_1<StructuredDataKeys1_21_11, EntityDataTypes26_1> V26_1 = new Types26_1<>(StructuredDataKeys1_21_11::new, EntityDataTypes26_1::new);
}
@@ -39,10 +39,31 @@ import java.util.List;
*/
public interface VersionedTypesHolder {
/**
* Returns the unmapped item stack type
*
* @return unmapped item stack type
*/
Type<Item> item();
Type<Item[]> itemArray();
/**
* Returns the unmapped item stack template type, used for certain recipes/templates in 26.1+.
*
* @return unmapped item stack template type
*/
Type<Item> itemTemplate();
Type<Item> optionalItemTemplate();
Type<Item[]> itemTemplateArray();
/**
* Returns the unmapped item cost type, used in merchant offers.
*
* @return unmapped item cost type
*/
Type<Item> itemCost();
Type<Item> optionalItemCost();
+1 -1
View File
@@ -8,7 +8,7 @@ repositories {
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.3.1")
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.4.1")
// A nice no-conflict comment for patching in downgrading
}
@@ -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) {
@@ -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
@@ -76,6 +76,7 @@ import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.Protocol1_20_3To1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.Protocol1_20To1_20_2;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.Protocol1_21_11To26_1;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.Protocol1_21_4To1_21_5;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.Protocol1_21_5To1_21_6;
@@ -213,6 +214,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
registerProtocol(new Protocol1_21_6To1_21_7(), ProtocolVersion.v1_21_7, ProtocolVersion.v1_21_6);
registerProtocol(new Protocol1_21_7To1_21_9(), ProtocolVersion.v1_21_9, ProtocolVersion.v1_21_7);
registerProtocol(new Protocol1_21_9To1_21_11(), ProtocolVersion.v1_21_11, ProtocolVersion.v1_21_9);
registerProtocol(new Protocol1_21_11To26_1(), ProtocolVersion.v26_1, ProtocolVersion.v1_21_11);
}
@Override
@@ -478,6 +478,19 @@ public class PacketWrapperImpl implements PacketWrapper {
this.packetValues.clear();
}
@Override
public void rewindReader(final int values) {
if (allActionsRead) {
return;
}
final int size = packetValues.size();
Preconditions.checkArgument(values <= size, "Tried resetting more values than there are readable values");
for (int i = size - 1; i >= size - values; i--) {
this.readableObjects.addFirst(this.packetValues.remove(i));
}
}
@Override
public void sendToServerRaw() throws InformativeException {
sendToServerRaw(true);
@@ -584,6 +597,16 @@ public class PacketWrapperImpl implements PacketWrapper {
this.allActionsRead = allActionsRead;
}
@Override
public void consumeReadsOnly(final Runnable runnable) {
this.allActionsRead = true;
try {
runnable.run();
} finally {
this.allActionsRead = false;
}
}
@Override
public String toString() {
return "PacketWrapper{" +
@@ -21,24 +21,23 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.RecipeDisplayRewriter1_21_5;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import com.viaversion.viaversion.rewriter.block.BlockRewriter1_21_5;
// To replace if needed:
// ChunkType1_21_5
// ChunkType26_1
// RecipeDisplayRewriter
// Types1_21_4, Types1_OLD
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21_6, ServerboundPacket1_21_6, Protocol1_98To1_99> {
final class BlockItemPacketRewriter99_1 extends StructuredItemRewriter<ClientboundPacket26_1, ServerboundPacket1_21_9, Protocol98_1To99_1> {
public BlockItemPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
public BlockItemPacketRewriter99_1(final Protocol98_1To99_1 protocol) {
super(protocol);
}
@@ -47,32 +46,32 @@ final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Clientbou
// Register block and block state id changes
// Other places using block state id mappings: Spawn particle, entity data, entity spawn (falling blocks)
// Tags and statistics use block (!) ids
final BlockRewriter<ClientboundPacket1_21_6> blockRewriter = new BlockRewriter1_21_5<>(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21_6.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_6.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_6.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_6.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_6.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_21_5::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_6.BLOCK_ENTITY_DATA);
final BlockRewriter<ClientboundPacket26_1> blockRewriter = new BlockRewriter1_21_5<>(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets26_1.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets26_1.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets26_1.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets26_1.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets26_1.LEVEL_CHUNK_WITH_LIGHT, ChunkType26_1::new);
blockRewriter.registerBlockEntityData(ClientboundPackets26_1.BLOCK_ENTITY_DATA);
// Registers item id changes
// Other places using item ids are: Entity data, tags, statistics, effect
// registerOpenScreen(ClientboundPackets1_21_6.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
registerSetCursorItem(ClientboundPackets1_21_6.SET_CURSOR_ITEM);
registerSetPlayerInventory(ClientboundPackets1_21_6.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets1_21_6.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets1_21_6.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_6.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_6.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_6.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_6.MERCHANT_OFFERS);
// registerOpenScreen(ClientboundPackets26_1.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
registerSetCursorItem(ClientboundPackets26_1.SET_CURSOR_ITEM);
registerSetPlayerInventory(ClientboundPackets26_1.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets26_1.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets26_1.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets26_1.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets26_1.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets26_1.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets26_1.MERCHANT_OFFERS);
registerContainerClick1_21_5(ServerboundPackets1_21_6.CONTAINER_CLICK);
registerSetCreativeModeSlot1_21_5(ServerboundPackets1_21_6.SET_CREATIVE_MODE_SLOT);
final RecipeDisplayRewriter<ClientboundPacket1_21_6> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_6.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_6.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_6.PLACE_GHOST_RECIPE);
final RecipeDisplayRewriter<ClientboundPacket26_1> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets26_1.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets26_1.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets26_1.PLACE_GHOST_RECIPE);
// OR do this if serialization of recipes changed and override the relevant method
// Add new serializers to RecipeDisplayRewriter, or extend the last one for changes
}
@@ -19,12 +19,12 @@ package com.viaversion.viaversion.protocols.template;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
final class ComponentRewriter1_99 extends NBTComponentRewriter<ClientboundPacket1_21_6> {
final class ComponentRewriter99_1 extends NBTComponentRewriter<ClientboundPacket26_1> {
public ComponentRewriter1_99(final Protocol1_98To1_99 protocol) {
public ComponentRewriter99_1(final Protocol98_1To99_1 protocol) {
super(protocol);
}
@@ -18,36 +18,36 @@
package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.rewriter.EntityRewriter;
// Replace if needed
// VersionedTypes
// EntityTypes1_21_9
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21_6, Protocol1_98To1_99> {
// EntityTypes1_21_11
final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_1, Protocol98_1To99_1> {
public EntityPacketRewriter1_99(final Protocol1_98To1_99 protocol) {
public EntityPacketRewriter99_1(final Protocol98_1To99_1 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
// Tracks entities, applies entity data rewrites registered below, untracks entities
registerTrackerWithData1_21_9(ClientboundPackets1_21_6.ADD_ENTITY, EntityTypes1_21_9.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_6.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets1_21_6.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets1_21_6.PLAYER_ABILITIES);
registerGameEvent(ClientboundPackets1_21_6.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets1_21_6.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_6.RESPAWN);
registerTrackerWithData1_21_9(ClientboundPackets26_1.ADD_ENTITY, EntityTypes1_21_11.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets26_1.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets26_1.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets26_1.PLAYER_ABILITIES);
registerGameEvent(ClientboundPackets26_1.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets26_1.LOGIN);
registerRespawn1_20_5(ClientboundPackets26_1.RESPAWN);
}
@Override
protected void registerRewrites() {
final EntityDataTypes1_21_9 entityDataTypes = protocol.mappedTypes().entityDataTypes();
final EntityDataTypes26_1 entityDataTypes = protocol.mappedTypes().entityDataTypes();
filter().mapDataType(entityDataTypes::byId);
/* ... or something this if entity data classes changed
filter().mapDataType(typeId -> {
@@ -78,6 +78,6 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_9.getTypeFromId(type);
return EntityTypes1_21_11.getTypeFromId(type);
}
}
@@ -20,9 +20,9 @@ package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_5;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_11;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
@@ -30,12 +30,12 @@ import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.data.item.ItemHasherBase;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundConfigurationPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundConfigurationPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
@@ -47,65 +47,64 @@ import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_98To1_99, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99 - move the latter two to a rewriter package
// ClientboundPacket1_21_6
// ServerboundPacket1_21_6
// EntityTypes1_21_9 (MAPPED type)
// VersionedTypes.V1_21_9
// 1.99, 1.98
final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6, ClientboundPacket1_21_6, ServerboundPacket1_21_6, ServerboundPacket1_21_6> {
// ClientboundPacket26_1
// ServerboundPacket1_21_9
// EntityDataTypes26_1 (MAPPED type)
// VersionedTypes.V26_1
// 98.1, 99.1
final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket1_21_9> {
public static final MappingData MAPPINGS = new MappingDataBase("1.98", "1.99");
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
private final ParticleRewriter<ClientboundPacket1_21_6> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPacket1_21_6> tagRewriter = new TagRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket1_21_6> componentRewriter = new ComponentRewriter1_99(this);
public static final MappingData MAPPINGS = new MappingDataBase("98.1", "99.1");
private final EntityPacketRewriter99_1 entityRewriter = new EntityPacketRewriter99_1(this);
private final BlockItemPacketRewriter99_1 itemRewriter = new BlockItemPacketRewriter99_1(this);
private final ParticleRewriter<ClientboundPacket26_1> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPacket26_1> tagRewriter = new TagRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket26_1> componentRewriter = new ComponentRewriter99_1(this);
private final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(this);
public Protocol1_98To1_99() {
public Protocol98_1To99_1() {
// Passing the class types into the super constructor is needed for automatic packet type id remapping, but can otherwise be omitted
super(ClientboundPacket1_21_6.class, ClientboundPacket1_21_6.class, ServerboundPacket1_21_6.class, ServerboundPacket1_21_6.class);
super(ClientboundPacket26_1.class, ClientboundPacket26_1.class, ServerboundPacket1_21_9.class, ServerboundPacket1_21_9.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
registerClientbound(ClientboundConfigurationPackets1_21_6.REGISTRY_DATA, registryDataRewriter::handle);
registerClientbound(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.registerGeneric(ClientboundPackets1_21_6.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_6.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundPackets26_1.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_9.UPDATE_TAGS);
// If needed for item or component changes
componentRewriter.registerOpenScreen1_14(ClientboundPackets1_21_6.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets1_21_6.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.DISCONNECT);
componentRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_6.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets1_21_6.TAB_LIST);
componentRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets1_21_6.SET_PLAYER_TEAM);
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_6.PLAYER_COMBAT_KILL);
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_6.PLAYER_INFO_UPDATE);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_6.SYSTEM_CHAT);
componentRewriter.registerDisguisedChat(ClientboundPackets1_21_6.DISGUISED_CHAT);
componentRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_6.PLAYER_CHAT);
componentRewriter.registerSetObjective(ClientboundPackets1_21_6.SET_OBJECTIVE);
componentRewriter.registerSetScore1_20_3(ClientboundPackets1_21_6.SET_SCORE);
componentRewriter.registerOpenScreen1_14(ClientboundPackets26_1.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets26_1.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.DISCONNECT);
componentRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_9.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets26_1.TAB_LIST);
componentRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets26_1.SET_PLAYER_TEAM);
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets26_1.PLAYER_COMBAT_KILL);
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets26_1.PLAYER_INFO_UPDATE);
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SYSTEM_CHAT);
componentRewriter.registerDisguisedChat(ClientboundPackets26_1.DISGUISED_CHAT);
componentRewriter.registerPlayerChat1_21_5(ClientboundPackets26_1.PLAYER_CHAT);
componentRewriter.registerSetObjective(ClientboundPackets26_1.SET_OBJECTIVE);
componentRewriter.registerSetScore1_20_3(ClientboundPackets26_1.SET_SCORE);
componentRewriter.registerPing();
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_6.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_9(ClientboundPackets1_21_6.EXPLODE); // Rewrites the included sound and particles
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets26_1.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_9(ClientboundPackets26_1.EXPLODE); // Rewrites the included sound and particles
final SoundRewriter<ClientboundPacket1_21_6> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_6.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_6.SOUND_ENTITY);
final SoundRewriter<ClientboundPacket26_1> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets26_1.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets26_1.SOUND_ENTITY);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_6.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_6.UPDATE_ATTRIBUTES);
new StatisticsRewriter<>(this).register(ClientboundPackets26_1.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets26_1.UPDATE_ATTRIBUTES);
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
/*new CommandRewriter1_19_4<>(this) {
@@ -118,13 +117,13 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
super.handleArgument(wrapper, argumentType);
}
}
}.registerDeclareCommands1_19(ClientboundPackets1_21_6.COMMANDS);*/
}.registerDeclareCommands1_19(ClientboundPackets26_1.COMMANDS);*/
}
@Override
protected void onMappingDataLoaded() {
// Uncomment this if the entity types enum has been newly added specifically for this Protocol
// EntityTypes1_21_9.initialize(this);
// EntityTypes1_21_11.initialize(this);
// Uncomment if a new particle was added = ids shifted; requires a new Types_ class copied from the last
/*mappedTypes().particle.filler(this)
@@ -145,7 +144,7 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
.reader("effect", ParticleType.Readers.SPELL)
.reader("instant_effect", ParticleType.Readers.SPELL)
.reader("flash", ParticleType.Readers.COLOR)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));*/
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemTemplateType()));*/
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
}
@@ -153,7 +152,7 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
@Override
public void init(final UserConnection connection) {
// Register the entity tracker - used for entity id/entity data rewriting AND for tracking world data sent to the client (then used for chunk data rewriting)
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_9.PLAYER));
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
}
@@ -165,12 +164,12 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
}
@Override
public EntityPacketRewriter1_99 getEntityRewriter() {
public EntityPacketRewriter99_1 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter1_99 getItemRewriter() {
public BlockItemPacketRewriter99_1 getItemRewriter() {
return itemRewriter;
}
@@ -180,37 +179,37 @@ final class Protocol1_98To1_99 extends AbstractProtocol<ClientboundPacket1_21_6,
}
@Override
public ParticleRewriter<ClientboundPacket1_21_6> getParticleRewriter() {
public ParticleRewriter<ClientboundPacket26_1> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21_6> getTagRewriter() {
public TagRewriter<ClientboundPacket26_1> getTagRewriter() {
return tagRewriter;
}
@Override
public NBTComponentRewriter<ClientboundPacket1_21_6> getComponentRewriter() {
public NBTComponentRewriter<ClientboundPacket26_1> getComponentRewriter() {
return componentRewriter;
}
@Override
public Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_9> types() {
return VersionedTypes.V1_21_9;
public Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes26_1> types() {
return VersionedTypes.V26_1;
}
@Override
public Types1_20_5<StructuredDataKeys1_21_5, EntityDataTypes1_21_9> mappedTypes() {
return VersionedTypes.V1_21_9;
public Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes26_1> mappedTypes() {
return VersionedTypes.V26_1;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21_6, ClientboundPacket1_21_6, ServerboundPacket1_21_6, ServerboundPacket1_21_6> createPacketTypesProvider() {
protected PacketTypesProvider<ClientboundPacket26_1, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket1_21_9> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_6.class, ClientboundConfigurationPackets1_21_6.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_6.class, ClientboundConfigurationPackets1_21_6.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_6.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_6.class)
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets26_1.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets26_1.class, ClientboundConfigurationPackets1_21_9.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_6.class, ServerboundConfigurationPackets1_21_9.class)
);
}
}
@@ -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 {
@@ -130,17 +130,6 @@ public final class Protocol1_19_1To1_19_3 extends AbstractProtocol<ClientboundPa
default -> super.handleArgument(wrapper, argumentType);
}
}
@Override
public String handleArgumentType(final String argumentType) {
return switch (argumentType) {
case "minecraft:resource" -> "minecraft:resource_key";
case "minecraft:resource_or_tag" -> "minecraft:resource_or_tag_key";
case "minecraft:entity_summon", "minecraft:item_enchantment", "minecraft:mob_effect" ->
"minecraft:resource";
default -> argumentType;
};
}
};
commandRewriter.registerDeclareCommands1_19(ClientboundPackets1_19_1.COMMANDS);
@@ -63,6 +63,11 @@ public final class EntityPacketRewriter1_19_4 extends EntityRewriter<Clientbound
final CompoundTag damageTypeRegistry = protocol.getMappingData().damageTypesRegistry();
registry.put("minecraft:damage_type", damageTypeRegistry);
final CompoundTag trimMaterialRegistry = new CompoundTag();
trimMaterialRegistry.putString("type", "minecraft:trim_material");
trimMaterialRegistry.put("value", new ListTag<>(CompoundTag.class));
registry.put("minecraft:trim_material", trimMaterialRegistry);
final ListTag<CompoundTag> biomes = TagUtil.getRegistryEntries(registry, "worldgen/biome");
for (final CompoundTag biomeTag : biomes) {
final CompoundTag biomeData = biomeTag.getCompoundTag("element");
@@ -827,11 +827,12 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
potionEffectToTag(effectTag, effect);
customEffects.add(effectTag);
}
tag.put("custom_effects", customEffects);
if (!customEffects.isEmpty()) {
tag.put("custom_effects", customEffects);
}
if (value.customName() != null) {
tag.putString("custom_name", value.customName());
}
tag.put("custom_effects", customEffects);
return tag;
}
@@ -425,7 +425,9 @@ public final class StructuredDataConverter {
customPotionEffectsTag.add(effectTag);
}
tag.put("custom_potion_effects", customPotionEffectsTag);
if (!customPotionEffectsTag.isEmpty()) {
tag.put("custom_potion_effects", customPotionEffectsTag);
}
});
register(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, (data, tag) -> {
final ListTag<CompoundTag> effectsTag = new ListTag<>(CompoundTag.class);
@@ -25,6 +25,8 @@ import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.TagData;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_19_4;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.Direction;
@@ -57,6 +59,8 @@ import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -344,15 +348,24 @@ public final class Protocol1_20To1_20_2 extends AbstractProtocol<ClientboundPack
// The client includes vanilla as the default feature when initially leaving the login phase
final LastTags lastTags = connection.get(LastTags.class);
boolean sentTags = false;
if (lastTags != null) {
if (lastTags.sentDuringConfigPhase()) {
lastTags.setSentDuringConfigPhase(false);
sentTags = true;
} else {
// The server might still follow up with a tags packet, but we wouldn't know
lastTags.sendLastTags(connection);
sentTags = lastTags.sendLastTags(connection);
}
}
if (!sentTags) {
// Send an empty tags packet to allow adding to it in later protocols
final PacketWrapper packet = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, connection);
packet.write(Types.VAR_INT, 0);
packet.send(Protocol1_20To1_20_2.class);
}
if (lastResourcePack != null && connection.getProtocolInfo().protocolVersion() == ProtocolVersion.v1_20_2) {
// The client for some reason drops the resource pack when reentering the configuration state
final PacketWrapper resourcePackPacket = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK, connection);
@@ -48,9 +48,9 @@ public class LastTags implements StorableObject {
}
}
public void sendLastTags(final UserConnection connection) {
public boolean sendLastTags(final UserConnection connection) {
if (registryTags.isEmpty()) {
return;
return false;
}
final PacketWrapper packet = PacketWrapper.create(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, connection);
@@ -64,6 +64,7 @@ public class LastTags implements StorableObject {
}
}
packet.send(Protocol1_20To1_20_2.class);
return true;
}
public void setSentDuringConfigPhase(final boolean sentDuringConfigPhase) {
@@ -0,0 +1,394 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_21_11to26_1;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
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.EntityDataTypes1_21_11;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
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;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
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_11to26_1.data.MappingData26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.rewriter.BlockItemPacketRewriter26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.rewriter.ComponentRewriter26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.rewriter.EntityPacketRewriter26_1;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPackets1_21_11;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
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.text.NBTComponentRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.Map;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
public final class Protocol1_21_11To26_1 extends AbstractProtocol<ClientboundPacket1_21_11, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket26_1> {
public static final MappingData26_1 MAPPINGS = new MappingData26_1();
private final EntityPacketRewriter26_1 entityRewriter = new EntityPacketRewriter26_1(this);
private final BlockItemPacketRewriter26_1 itemRewriter = new BlockItemPacketRewriter26_1(this);
private final ParticleRewriter<ClientboundPacket1_21_11> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPacket1_21_11> tagRewriter = new TagRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket1_21_11> componentRewriter = new ComponentRewriter26_1(this);
private final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(this);
public Protocol1_21_11To26_1() {
super(ClientboundPacket1_21_11.class, ClientboundPacket26_1.class, ServerboundPacket1_21_9.class, ServerboundPacket26_1.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
registerFinishConfiguration(ClientboundConfigurationPackets1_21_9.FINISH_CONFIGURATION, wrapper -> {
final PacketWrapper clocksPacket = wrapper.create(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA);
clocksPacket.write(Types.STRING, "world_clock");
clocksPacket.write(Types.REGISTRY_ENTRY_ARRAY, new RegistryEntry[]{new RegistryEntry("minecraft:overworld", new CompoundTag())});
clocksPacket.send(Protocol1_21_11To26_1.class);
sendSoundVariants(wrapper, "cat_sound_variant", MAPPINGS.catSoundVariants());
sendSoundVariants(wrapper, "cow_sound_variant", MAPPINGS.cowSoundVariants());
sendSoundVariants(wrapper, "pig_sound_variant", MAPPINGS.pigSoundVariants());
sendSoundVariants(wrapper, "chicken_sound_variant", MAPPINGS.chickenSoundVariants());
});
addRequiredRegistryEntries();
registryDataRewriter.addHandler("timeline", (key, tag) -> tag.putString("clock", "overworld"));
registryDataRewriter.addHandler("wolf_sound_variant", (key, tag) -> {
final CompoundTag sounds = new CompoundTag();
for (final Map.Entry<String, Tag> entry : tag.entrySet()) {
sounds.put(entry.getKey(), entry.getValue());
}
tag.clear();
sounds.putString("step_sound", "entity.wolf.step");
tag.put("adult_sounds", sounds);
tag.put("baby_sounds", sounds.copy());
});
registryDataRewriter.addHandler("wolf_variant", (key, tag) -> {
final Tag assets = tag.get("assets");
tag.put("baby_assets", assets.copy());
});
registryDataRewriter.addHandler("frog_variant", (key, tag) -> swapEntityNameAffix("frog", tag));
swapAffixAndAddAssetId("chicken_variant", "chicken");
swapAffixAndAddAssetId("cow_variant", "cow");
swapAffixAndAddAssetId("pig_variant", "pig");
registryDataRewriter.addHandler("cat_variant", (key, tag) -> {
addEntityNamePrefix("cat", tag);
addBabyAssetId("cat", tag);
});
registryDataRewriter.addHandler("dimension_type", (key, tag) -> {
tag.putBoolean("has_ender_dragon_fight", Key.equals(key, "the_end"));
final CompoundTag attributes = tag.getCompoundTag("attributes");
if (attributes != null) {
final int ambientLightColor = switch (Key.stripMinecraftNamespace(key)) {
case "the_end" -> -12630209;
case "the_nether" -> -13621215;
case "overworld" -> -16119286;
default -> -16777216;
};
attributes.putInt("visual/ambient_light_color", ambientLightColor);
}
});
registerClientbound(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA, registryDataRewriter::handle);
tagRewriter.registerGeneric(ClientboundPackets1_21_11.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_9.UPDATE_TAGS);
componentRewriter.registerOpenScreen1_14(ClientboundPackets1_21_11.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_11.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_11.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_11.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets1_21_11.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_11.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets1_21_11.TAB_LIST);
componentRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets1_21_11.SET_PLAYER_TEAM);
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_11.PLAYER_COMBAT_KILL);
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_11.PLAYER_INFO_UPDATE);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_11.SYSTEM_CHAT);
componentRewriter.registerDisguisedChat(ClientboundPackets1_21_11.DISGUISED_CHAT);
componentRewriter.registerPlayerChat1_21_5(ClientboundPackets1_21_11.PLAYER_CHAT);
componentRewriter.registerPing();
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets1_21_11.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_9(ClientboundPackets1_21_11.EXPLODE);
final SoundRewriter<ClientboundPacket1_21_11> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_11.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_11.SOUND_ENTITY);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_11.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_11.UPDATE_ATTRIBUTES);
registerClientbound(ClientboundPackets1_21_11.SET_TIME, wrapper -> {
wrapper.passthrough(Types.LONG); // Game time
final long dayTime = wrapper.read(Types.LONG);
final boolean tickDayTime = wrapper.read(Types.BOOLEAN);
wrapper.write(Types.VAR_INT, 1); // One!
wrapper.write(Types.VAR_INT, 0); // Overworld clock
wrapper.write(Types.VAR_LONG, dayTime); // Total ticks
wrapper.write(Types.FLOAT, 0F); // Partial tick
wrapper.write(Types.FLOAT, tickDayTime ? 1F : 0F); // Tick rate
});
cancelServerbound(ServerboundPackets26_1.SET_GAME_RULE);
}
private void sendSoundVariants(final PacketWrapper wrapper, final String key, final CompoundTag tag) {
final PacketWrapper clocksPacket = wrapper.create(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA);
clocksPacket.write(Types.STRING, key);
clocksPacket.write(Types.REGISTRY_ENTRY_ARRAY, registryDataRewriter.entriesFromTag(tag));
clocksPacket.send(Protocol1_21_11To26_1.class);
}
private void addRequiredRegistryEntries() {
// Add a few possibly missing registry entries required by delayed default item creation.
// These are some of the things that brought us the glorious EitherHolderType before
final CompoundTag spearDamageType = new CompoundTag();
spearDamageType.putFloat("exhaustion", 0.1F);
spearDamageType.putString("message_id", "spear");
spearDamageType.putString("scaling", "when_caused_by_living_non_player");
registryDataRewriter.addEntries("damage_type", new RegistryEntry("spear", spearDamageType));
final CompoundTag coldChicken = new CompoundTag();
coldChicken.putString("asset_id", "entity/chicken/chicken_cold");
coldChicken.putString("baby_asset_id", "entity/chicken/chicken_cold_baby");
coldChicken.putString("model", "cold");
final CompoundTag warmChicken = new CompoundTag();
warmChicken.putString("asset_id", "entity/chicken/chicken_warm");
warmChicken.putString("baby_asset_id", "entity/chicken/chicken_warm_baby");
registryDataRewriter.addEntries("chicken_variant", new RegistryEntry("cold", coldChicken), new RegistryEntry("warm", warmChicken));
final CompoundTag ponderGoatHornInstrument = new CompoundTag();
final CompoundTag ponderGoatHornDescription = new CompoundTag();
ponderGoatHornDescription.putString("translate", "instrument.minecraft.ponder_goat_horn");
ponderGoatHornInstrument.put("description", ponderGoatHornDescription);
ponderGoatHornInstrument.putString("sound_event", "item.goat_horn.sound.0");
ponderGoatHornInstrument.putFloat("use_duration", 7F);
ponderGoatHornInstrument.putFloat("range", 256F);
registryDataRewriter.addEntries("instrument", new RegistryEntry("spear", ponderGoatHornInstrument));
addJukeboxPlayables("11", "13", "5", "blocks", "cat", "chirp", "far", "mall", "mellohi", "otherside", "pigstep", "relic", "stal", "strad", "wait", "ward", "creator", "creator_music_box", "lava_chicken", "tears", "precipice");
addTrimMaterials("quartz", "iron", "netherite", "redstone", "copper", "gold", "emerald", "diamond", "lapis", "amethyst", "resin");
}
private void addTrimMaterials(final String... trimMaterials) {
for (final String trimMaterial : trimMaterials) {
final CompoundTag materialTag = new CompoundTag();
final CompoundTag materialDescription = new CompoundTag();
materialDescription.putString("translate", "trim_material.minecraft." + trimMaterial);
materialTag.put("description", materialDescription);
materialTag.putString("asset_name", trimMaterial);
registryDataRewriter.addEntries("trim_material", new RegistryEntry(trimMaterial, materialTag));
}
}
private void addJukeboxPlayables(final String... songs) {
for (final String song : songs) {
final CompoundTag songTag = new CompoundTag();
final CompoundTag songDescription = new CompoundTag();
songDescription.putString("translate", "jukebox_song.minecraft." + song);
songTag.put("description", songDescription);
songTag.putString("sound_event", "music_disc." + song);
songTag.putFloat("length_in_seconds", 175F);
songTag.putInt("comparator_output", 10);
registryDataRewriter.addEntries("jukebox_song", new RegistryEntry(song, songTag));
}
}
private void swapAffixAndAddAssetId(final String registryKey, final String affix) {
registryDataRewriter.addHandler(registryKey, (key, tag) -> {
swapEntityNameAffix(affix, tag);
addBabyAssetId(affix, tag);
});
}
private void addBabyAssetId(final String key, final CompoundTag tag) {
final String assetId = tag.getString("asset_id");
tag.putString("baby_asset_id", assetId + "_baby");
}
private void addEntityNamePrefix(final String key, final CompoundTag tag) {
// e.g. entity/cat/jellie -> entity/cat/cat_jellie
final StringTag assetIdTag = tag.getStringTag("asset_id");
final String assetId = assetIdTag.getValue();
assetIdTag.setValue(assetId.replace(key + "/", key + "/" + key + "_"));
}
private void swapEntityNameAffix(final String key, final CompoundTag tag) {
final StringTag assetIdTag = tag.getStringTag("asset_id");
final String assetId = assetIdTag.getValue();
if (assetId.endsWith("_" + key)) {
// e.g. entity/frog/warm_frog -> entity/frog/frog_warm
final String mappedAsset = assetId.substring(0, assetId.length() - key.length() - 1)
.replace(key + "/", key + "/" + key + "_");
assetIdTag.setValue(mappedAsset);
}
}
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
}
@Override
protected void onMappingDataLoaded() {
mappedTypes().particle.filler(this)
.reader("block", ParticleType.Readers.BLOCK)
.reader("block_marker", ParticleType.Readers.BLOCK)
.reader("dust_pillar", ParticleType.Readers.BLOCK)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("block_crumble", ParticleType.Readers.BLOCK)
.reader("dust", ParticleType.Readers.DUST1_21_2)
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION1_21_2)
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK)
.reader("entity_effect", ParticleType.Readers.COLOR)
.reader("tinted_leaves", ParticleType.Readers.COLOR)
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
.reader("dragon_breath", ParticleType.Readers.POWER)
.reader("effect", ParticleType.Readers.SPELL)
.reader("instant_effect", ParticleType.Readers.SPELL)
.reader("flash", ParticleType.Readers.COLOR)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemTemplateType()));
mappedTypes().structuredData.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT26_1,
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS1_21_5,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS26_1, StructuredDataKey.PROVIDES_BANNER_PATTERNS26_1,
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
StructuredDataKey.INTANGIBLE_PROJECTILE, StructuredDataKey.STORED_ENCHANTMENTS1_21_5, StructuredDataKey.DYED_COLOR1_21_5,
StructuredDataKey.MAP_COLOR, StructuredDataKey.MAP_ID, StructuredDataKey.MAP_DECORATIONS, StructuredDataKey.MAP_POST_PROCESSING,
StructuredDataKey.POTION_CONTENTS1_21_2, StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, StructuredDataKey.WRITABLE_BOOK_CONTENT,
StructuredDataKey.WRITTEN_BOOK_CONTENT, StructuredDataKey.TRIM1_21_5, StructuredDataKey.DEBUG_STICK_STATE, StructuredDataKey.ENTITY_DATA1_21_9,
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA1_21_9, StructuredDataKey.INSTRUMENT26_1,
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
StructuredDataKey.PROFILE1_21_9, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_21_9, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_21_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE26_1, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_6,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2, StructuredDataKey.ATTACK_RANGE,
StructuredDataKey.USE_COOLDOWN, StructuredDataKey.DAMAGE, StructuredDataKey.EQUIPPABLE1_21_6, StructuredDataKey.ITEM_MODEL,
StructuredDataKey.GLIDER, StructuredDataKey.TOOLTIP_STYLE, StructuredDataKey.DEATH_PROTECTION, StructuredDataKey.WEAPON,
StructuredDataKey.POTION_DURATION_SCALE, StructuredDataKey.VILLAGER_VARIANT, StructuredDataKey.WOLF_VARIANT, StructuredDataKey.WOLF_COLLAR,
StructuredDataKey.FOX_VARIANT, StructuredDataKey.SALMON_SIZE, StructuredDataKey.PARROT_VARIANT, StructuredDataKey.TROPICAL_FISH_PATTERN,
StructuredDataKey.TROPICAL_FISH_BASE_COLOR, StructuredDataKey.TROPICAL_FISH_PATTERN_COLOR, StructuredDataKey.MOOSHROOM_VARIANT,
StructuredDataKey.RABBIT_VARIANT, StructuredDataKey.PIG_VARIANT, StructuredDataKey.FROG_VARIANT, StructuredDataKey.HORSE_VARIANT,
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT, StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_VARIANT,
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL26_1,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT26_1, StructuredDataKey.WOLF_SOUND_VARIANT,
StructuredDataKey.USE_EFFECTS, StructuredDataKey.MINIMUM_ATTACK_CHARGE, StructuredDataKey.DAMAGE_TYPE26_1, StructuredDataKey.PIERCING_WEAPON,
StructuredDataKey.KINETIC_WEAPON, StructuredDataKey.SWING_ANIMATION, StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT26_1, StructuredDataKey.ADDITIONAL_TRADE_COST,
StructuredDataKey.DYE, StructuredDataKey.PIG_SOUND_VARIANT, StructuredDataKey.COW_SOUND_VARIANT, StructuredDataKey.CHICKEN_SOUND_VARIANT, StructuredDataKey.CAT_SOUND_VARIANT);
tagRewriter.addEmptyTags(RegistryType.DAMAGE_TYPE, "damages_helmet", "bypasses_armor", "bypasses_shield", "bypasses_invulnerability", "bypasses_cooldown", "bypasses_effects",
"bypasses_resistance", "bypasses_enchantments", "is_fire", "is_projectile", "witch_resistant_to", "is_explosion", "is_fall", "is_drowning", "is_freezing", "is_lightning", "no_anger",
"no_impact", "always_most_significant_fall", "wither_immune_to", "ignites_armor_stands", "burns_armor_stands", "avoids_guardian_thorns", "always_triggers_silverfish",
"always_hurts_ender_dragons", "no_knockback", "always_kills_armor_stands", "can_break_armor_stand", "bypasses_wolf_armor", "is_player_attack",
"burn_from_stepping", "panic_causes", "panic_environmental_causes", "mace_smash");
tagRewriter.addEmptyTags(RegistryType.BANNER_PATTERN, "no_item_required", "pattern_item/flower", "pattern_item/creeper", "pattern_item/skull", "pattern_item/mojang",
"pattern_item/globe", "pattern_item/piglin", "pattern_item/flow", "pattern_item/guster", "pattern_item/field_masoned", "pattern_item/bordure_indented");
super.onMappingDataLoaded();
}
@Override
public MappingData getMappingData() {
return MAPPINGS;
}
@Override
public EntityPacketRewriter26_1 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter26_1 getItemRewriter() {
return itemRewriter;
}
@Override
public RegistryDataRewriter getRegistryDataRewriter() {
return registryDataRewriter;
}
@Override
public ParticleRewriter<ClientboundPacket1_21_11> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21_11> getTagRewriter() {
return tagRewriter;
}
@Override
public NBTComponentRewriter<ClientboundPacket1_21_11> getComponentRewriter() {
return componentRewriter;
}
@Override
public Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes1_21_11> types() {
return VersionedTypes.V1_21_11;
}
@Override
public Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes26_1> mappedTypes() {
return VersionedTypes.V26_1;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21_11, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket26_1> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_11.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, ServerboundPackets26_1.class, ServerboundConfigurationPackets1_21_9.class)
);
}
}
@@ -0,0 +1,68 @@
/*
* 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.v1_21_11to26_1.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
public final class MappingData26_1 extends MappingDataBase {
private IntSet fluidBlockStates;
private CompoundTag catSoundVariants;
private CompoundTag cowSoundVariants;
private CompoundTag pigSoundVariants;
private CompoundTag chickenSoundVariants;
public MappingData26_1() {
super("1.21.11", "26.1");
}
@Override
protected void loadExtras(final CompoundTag data) {
final CompoundTag tag = MappingDataLoader.INSTANCE.loadNBTFromFile("sound-variant-registries-26.1.nbt");
catSoundVariants = tag.getCompoundTag("cat_sound_variant");
cowSoundVariants = tag.getCompoundTag("cow_sound_variant");
pigSoundVariants = tag.getCompoundTag("pig_sound_variant");
chickenSoundVariants = tag.getCompoundTag("chicken_sound_variant");
fluidBlockStates = new IntOpenHashSet(MappingDataLoader.INSTANCE.loadNBTFromFile("fluids-26.1.nbt").getIntArrayTag("fluids").getValue());
}
public CompoundTag catSoundVariants() {
return catSoundVariants;
}
public CompoundTag cowSoundVariants() {
return cowSoundVariants;
}
public CompoundTag pigSoundVariants() {
return pigSoundVariants;
}
public CompoundTag chickenSoundVariants() {
return chickenSoundVariants;
}
public IntSet fluidBlockStates() {
return fluidBlockStates;
}
}
@@ -0,0 +1,23 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_21_11to26_1.packet;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
public interface ClientboundPacket26_1 extends ClientboundPacketType {
}
@@ -0,0 +1,173 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_21_11to26_1.packet;
public enum ClientboundPackets26_1 implements ClientboundPacket26_1 {
BUNDLE_DELIMITER, // 0x00
ADD_ENTITY, // 0x01
ANIMATE, // 0x02
AWARD_STATS, // 0x03
BLOCK_CHANGED_ACK, // 0x04
BLOCK_DESTRUCTION, // 0x05
BLOCK_ENTITY_DATA, // 0x06
BLOCK_EVENT, // 0x07
BLOCK_UPDATE, // 0x08
BOSS_EVENT, // 0x09
CHANGE_DIFFICULTY, // 0x0A
CHUNK_BATCH_FINISHED, // 0x0B
CHUNK_BATCH_START, // 0x0C
CHUNKS_BIOMES, // 0x0D
CLEAR_TITLES, // 0x0E
COMMAND_SUGGESTIONS, // 0x0F
COMMANDS, // 0x10
CONTAINER_CLOSE, // 0x11
CONTAINER_SET_CONTENT, // 0x12
CONTAINER_SET_DATA, // 0x13
CONTAINER_SET_SLOT, // 0x14
COOKIE_REQUEST, // 0x15
COOLDOWN, // 0x16
CUSTOM_CHAT_COMPLETIONS, // 0x17
CUSTOM_PAYLOAD, // 0x18
DAMAGE_EVENT, // 0x19
DEBUG_BLOCK_VALUE, // 0x1A
DEBUG_CHUNK_VALUE, // 0x1B
DEBUG_ENTITY_VALUE, // 0x1C
DEBUG_EVENT, // 0x1D
DEBUG_SAMPLE, // 0x1E
DELETE_CHAT, // 0x1F
DISCONNECT, // 0x20
DISGUISED_CHAT, // 0x21
ENTITY_EVENT, // 0x22
ENTITY_POSITION_SYNC, // 0x23
EXPLODE, // 0x24
FORGET_LEVEL_CHUNK, // 0x25
GAME_EVENT, // 0x26
GAME_RULE_VALUES, // 0x27
GAME_EVENT_TEST_HIGHLIGHT_POS, // 0x28
MOUNT_SCREEN_OPEN, // 0x29
HURT_ANIMATION, // 0x2A
INITIALIZE_BORDER, // 0x2B
KEEP_ALIVE, // 0x2C
LEVEL_CHUNK_WITH_LIGHT, // 0x2D
LEVEL_EVENT, // 0x2E
LEVEL_PARTICLES, // 0x2F
LIGHT_UPDATE, // 0x30
LOGIN, // 0x31
LOW_DISK_SPACE_WARNING, // 0x32
MAP_ITEM_DATA, // 0x33
MERCHANT_OFFERS, // 0x34
MOVE_ENTITY_POS, // 0x35
MOVE_ENTITY_POS_ROT, // 0x36
MOVE_MINECART_ALONG_TRACK, // 0x37
MOVE_ENTITY_ROT, // 0x38
MOVE_VEHICLE, // 0x39
OPEN_BOOK, // 0x3A
OPEN_SCREEN, // 0x3B
OPEN_SIGN_EDITOR, // 0x3C
PING, // 0x3D
PONG_RESPONSE, // 0x3E
PLACE_GHOST_RECIPE, // 0x3F
PLAYER_ABILITIES, // 0x40
PLAYER_CHAT, // 0x41
PLAYER_COMBAT_END, // 0x42
PLAYER_COMBAT_ENTER, // 0x43
PLAYER_COMBAT_KILL, // 0x44
PLAYER_INFO_REMOVE, // 0x45
PLAYER_INFO_UPDATE, // 0x46
PLAYER_LOOK_AT, // 0x47
PLAYER_POSITION, // 0x48
PLAYER_ROTATION, // 0x49
RECIPE_BOOK_ADD, // 0x4A
RECIPE_BOOK_REMOVE, // 0x4B
RECIPE_BOOK_SETTINGS, // 0x4C
REMOVE_ENTITIES, // 0x4D
REMOVE_MOB_EFFECT, // 0x4E
RESET_SCORE, // 0x4F
RESOURCE_PACK_POP, // 0x50
RESOURCE_PACK_PUSH, // 0x51
RESPAWN, // 0x52
ROTATE_HEAD, // 0x53
SECTION_BLOCKS_UPDATE, // 0x54
SELECT_ADVANCEMENTS_TAB, // 0x55
SERVER_DATA, // 0x56
SET_ACTION_BAR_TEXT, // 0x57
SET_BORDER_CENTER, // 0x58
SET_BORDER_LERP_SIZE, // 0x59
SET_BORDER_SIZE, // 0x5A
SET_BORDER_WARNING_DELAY, // 0x5B
SET_BORDER_WARNING_DISTANCE, // 0x5C
SET_CAMERA, // 0x5D
SET_CHUNK_CACHE_CENTER, // 0x5E
SET_CHUNK_CACHE_RADIUS, // 0x5F
SET_CURSOR_ITEM, // 0x60
SET_DEFAULT_SPAWN_POSITION, // 0x61
SET_DISPLAY_OBJECTIVE, // 0x62
SET_ENTITY_DATA, // 0x63
SET_ENTITY_LINK, // 0x64
SET_ENTITY_MOTION, // 0x65
SET_EQUIPMENT, // 0x66
SET_EXPERIENCE, // 0x67
SET_HEALTH, // 0x68
SET_HELD_SLOT, // 0x69
SET_OBJECTIVE, // 0x6A
SET_PASSENGERS, // 0x6B
SET_PLAYER_INVENTORY, // 0x6C
SET_PLAYER_TEAM, // 0x6D
SET_SCORE, // 0x6E
SET_SIMULATION_DISTANCE, // 0x6F
SET_SUBTITLE_TEXT, // 0x70
SET_TIME, // 0x71
SET_TITLE_TEXT, // 0x72
SET_TITLES_ANIMATION, // 0x73
SOUND_ENTITY, // 0x74
SOUND, // 0x75
START_CONFIGURATION, // 0x76
STOP_SOUND, // 0x77
STORE_COOKIE, // 0x78
SYSTEM_CHAT, // 0x79
TAB_LIST, // 0x7A
TAG_QUERY, // 0x7B
TAKE_ITEM_ENTITY, // 0x7C
TELEPORT_ENTITY, // 0x7D
TEST_INSTANCE_BLOCK_STATUS, // 0x7E
TICKING_STATE, // 0x7F
TICKING_STEP, // 0x80
TRANSFER, // 0x81
UPDATE_ADVANCEMENTS, // 0x82
UPDATE_ATTRIBUTES, // 0x83
UPDATE_MOB_EFFECT, // 0x84
UPDATE_RECIPES, // 0x85
UPDATE_TAGS, // 0x86
PROJECTILE_POWER, // 0x87
CUSTOM_REPORT_DETAILS, // 0x88
SERVER_LINKS, // 0x89
TRACKED_WAYPOINT, // 0x8A
CLEAR_DIALOG, // 0x8B
SHOW_DIALOG; // 0x8C
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
}
@@ -0,0 +1,23 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_21_11to26_1.packet;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
public interface ServerboundPacket26_1 extends ServerboundPacketType {
}
@@ -0,0 +1,101 @@
/*
* 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.v1_21_11to26_1.packet;
public enum ServerboundPackets26_1 implements ServerboundPacket26_1 {
ACCEPT_TELEPORTATION, // 0x00
ATTACK, // 0x01
BLOCK_ENTITY_TAG_QUERY, // 0x02
BUNDLE_ITEM_SELECTED, // 0x03
CHANGE_DIFFICULTY, // 0x04
CHANGE_GAME_MODE, // 0x05
CHAT_ACK, // 0x06
CHAT_COMMAND, // 0x07
CHAT_COMMAND_SIGNED, // 0x08
CHAT, // 0x09
CHAT_SESSION_UPDATE, // 0x0A
CHUNK_BATCH_RECEIVED, // 0x0B
CLIENT_COMMAND, // 0x0C
CLIENT_TICK_END, // 0x0D
CLIENT_INFORMATION, // 0x0E
COMMAND_SUGGESTION, // 0x0F
CONFIGURATION_ACKNOWLEDGED, // 0x10
CONTAINER_BUTTON_CLICK, // 0x11
CONTAINER_CLICK, // 0x12
CONTAINER_CLOSE, // 0x13
CONTAINER_SLOT_STATE_CHANGED, // 0x14
COOKIE_RESPONSE, // 0x15
CUSTOM_PAYLOAD, // 0x16
DEBUG_SAMPLE_SUBSCRIPTION, // 0x17
EDIT_BOOK, // 0x18
ENTITY_TAG_QUERY, // 0x19
INTERACT, // 0x1A
JIGSAW_GENERATE, // 0x1B
KEEP_ALIVE, // 0x1C
LOCK_DIFFICULTY, // 0x1D
MOVE_PLAYER_POS, // 0x1E
MOVE_PLAYER_POS_ROT, // 0x1F
MOVE_PLAYER_ROT, // 0x20
MOVE_PLAYER_STATUS_ONLY, // 0x21
MOVE_VEHICLE, // 0x22
PADDLE_BOAT, // 0x23
PICK_ITEM_FROM_BLOCK, // 0x24
PICK_ITEM_FROM_ENTITY, // 0x25
PING_REQUEST, // 0x26
PLACE_RECIPE, // 0x27
PLAYER_ABILITIES, // 0x28
PLAYER_ACTION, // 0x29
PLAYER_COMMAND, // 0x2A
PLAYER_INPUT, // 0x2B
PLAYER_LOADED, // 0x2C
PONG, // 0x2D
RECIPE_BOOK_CHANGE_SETTINGS, // 0x2E
RECIPE_BOOK_SEEN_RECIPE, // 0x2F
RENAME_ITEM, // 0x30
RESOURCE_PACK, // 0x31
SEEN_ADVANCEMENTS, // 0x32
SELECT_TRADE, // 0x33
SET_BEACON, // 0x34
SET_CARRIED_ITEM, // 0x35
SET_COMMAND_BLOCK, // 0x36
SET_COMMAND_MINECART, // 0x37
SET_CREATIVE_MODE_SLOT, // 0x38
SET_GAME_RULE, // 0x39
SET_JIGSAW_BLOCK, // 0x3A
SET_STRUCTURE_BLOCK, // 0x3B
SET_TEST_BLOCK, // 0x3C
SIGN_UPDATE, // 0x3D
SPECTATE_ENTITY, // 0x3E
SWING, // 0x3F
TELEPORT_TO_ENTITY, // 0x40
TEST_INSTANCE_BLOCK_ACTION, // 0x41
USE_ITEM_ON, // 0x42
USE_ITEM, // 0x43
CUSTOM_CLICK_ACTION; // 0x44
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
}
@@ -0,0 +1,190 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_21_11to26_1.rewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.minecraft.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.StructuredItem;
import com.viaversion.viaversion.api.minecraft.item.data.BlocksAttacks;
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.JukeboxPlayable;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesBannerPatterns;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesTrimMaterial;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.Protocol1_21_11To26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.RecipeDisplayRewriter1_21_5;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPackets1_21_11;
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;
import com.viaversion.viaversion.util.Either;
import com.viaversion.viaversion.util.Key;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class BlockItemPacketRewriter26_1 extends StructuredItemRewriter<ClientboundPacket1_21_11, ServerboundPacket26_1, Protocol1_21_11To26_1> {
public BlockItemPacketRewriter26_1(final Protocol1_21_11To26_1 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPacket1_21_11> blockRewriter = new BlockRewriter1_21_5<>(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21_11.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_11.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_11.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_11.LEVEL_EVENT, 2001);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_11.BLOCK_ENTITY_DATA);
protocol.registerClientbound(ClientboundPackets1_21_11.LEVEL_CHUNK_WITH_LIGHT, wrapper -> {
final Chunk chunk = blockRewriter.handleChunk1_19(wrapper, ChunkType1_21_5::new, ChunkType26_1::new);
for (final ChunkSection section : chunk.getSections()) {
final DataPalette blockPalette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < blockPalette.size(); i++) {
final int id = blockPalette.idByIndex(i);
if (Protocol1_21_11To26_1.MAPPINGS.fluidBlockStates().contains(id)) {
// Needed for certain client-side fluid interactions
section.setFluidCount(section.getFluidCount() + 1);
}
}
}
blockRewriter.handleBlockEntities(chunk, wrapper.user());
});
registerSetCursorItem(ClientboundPackets1_21_11.SET_CURSOR_ITEM);
registerSetPlayerInventory(ClientboundPackets1_21_11.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets1_21_11.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets1_21_11.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_11.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_11.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_11.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_11.MERCHANT_OFFERS);
registerContainerClick1_21_5(ServerboundPackets26_1.CONTAINER_CLICK);
registerSetCreativeModeSlot1_21_5(ServerboundPackets26_1.SET_CREATIVE_MODE_SLOT);
final RecipeDisplayRewriter<ClientboundPacket1_21_11> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_11.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_11.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_11.PLACE_GHOST_RECIPE);
}
@Override
protected void handleItemDataComponentsToClient(final UserConnection connection, final Item item, final StructuredDataContainer container) {
// Uses null instead of empty items now
final Item[] containerData = container.get(protocol.types().structuredDataKeys().container);
if (containerData != null) {
for (int i = 0; i < containerData.length; i++) {
if (containerData[i].isEmpty()) {
containerData[i] = null;
}
}
}
upgradeData(protocol, container);
super.handleItemDataComponentsToClient(connection, item, container);
}
public static void upgradeData(final Protocol<?, ?, ?, ?> protocol, final StructuredDataContainer container) {
container.replace(StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, StructuredDataKey.JUKEBOX_PLAYABLE26_1, jukeboxPlayable -> upgradeHolder(protocol, jukeboxPlayable.song(), "jukebox_playable"));
container.replace(StructuredDataKey.INSTRUMENT1_21_5, StructuredDataKey.INSTRUMENT26_1, instrument -> upgradeHolder(protocol, instrument, "instrument"));
container.replace(StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5, StructuredDataKey.PROVIDES_TRIM_MATERIAL26_1, providesTrimMaterial -> upgradeHolder(protocol, providesTrimMaterial.material(), "trim_material"));
container.replace(StructuredDataKey.CHICKEN_VARIANT1_21_5, StructuredDataKey.CHICKEN_VARIANT26_1, chickenVariant -> upgradeEitherVariant(protocol, chickenVariant, "chicken_variant"));
container.replace(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT1_21_11, StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT26_1, nautilusVariant -> upgradeEitherVariant(protocol, nautilusVariant, "zombie_nautilus_variant"));
container.replace(StructuredDataKey.DAMAGE_TYPE1_21_11, StructuredDataKey.DAMAGE_TYPE26_1, damageType -> upgradeEitherVariant(protocol, damageType.id(), "damage_type"));
container.replace(StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5, StructuredDataKey.PROVIDES_BANNER_PATTERNS26_1, key -> new ProvidesBannerPatterns(HolderSet.of(key.original())));
container.replace(StructuredDataKey.DAMAGE_RESISTANT1_21_2, StructuredDataKey.DAMAGE_RESISTANT26_1, damageResistant -> new DamageResistant26_1(HolderSet.of(damageResistant.typesTagKey().original())));
container.replaceKey(StructuredDataKey.BLOCKS_ATTACKS1_21_5, StructuredDataKey.BLOCKS_ATTACKS26_1);
}
private static @Nullable Integer upgradeEitherVariant(final Protocol<?, ?, ?, ?> protocol, final Either<Integer, String> eitherHolder, final String registry) {
return eitherHolder.isLeft() ? eitherHolder.left() : registryIdOrNull(protocol, registry, eitherHolder.right());
}
private static <T> @Nullable Holder<T> upgradeHolder(final Protocol<?, ?, ?, ?> protocol, final EitherHolder<T> eitherHolder, final String registry) {
if (eitherHolder.hasHolder()) {
return eitherHolder.holder();
}
final Integer id = registryIdOrNull(protocol, registry, eitherHolder.key());
return id != null ? Holder.of((int) id) : null;
}
private static @Nullable Integer registryIdOrNull(final Protocol<?, ?, ?, ?> protocol, final String registry, final String key) {
final int id = protocol.getRegistryDataRewriter().getMappings(registry).keyToId(key);
return id != -1 ? id : null;
}
@Override
protected void handleItemDataComponentsToServer(final UserConnection connection, final Item item, final StructuredDataContainer container) {
final Item[] containerData = container.get(protocol.mappedTypes().structuredDataKeys().container);
if (containerData != null) {
for (int i = 0; i < containerData.length; i++) {
if (containerData[i] == null) {
containerData[i] = StructuredItem.empty();
}
}
}
downgradeData(container);
super.handleItemDataComponentsToServer(connection, item, container);
}
public static void downgradeData(final StructuredDataContainer container) {
container.replace(StructuredDataKey.JUKEBOX_PLAYABLE26_1, StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, jukeboxPlayable -> new JukeboxPlayable(jukeboxPlayable, true));
container.replace(StructuredDataKey.INSTRUMENT26_1, StructuredDataKey.INSTRUMENT1_21_5, EitherHolder::of);
container.replace(StructuredDataKey.PROVIDES_TRIM_MATERIAL26_1, StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5, providesTrimMaterial -> new ProvidesTrimMaterial(EitherHolder.of(providesTrimMaterial)));
container.replace(StructuredDataKey.CHICKEN_VARIANT26_1, StructuredDataKey.CHICKEN_VARIANT1_21_5, Either::left);
container.replace(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT26_1, StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT1_21_11, Either::left);
container.replace(StructuredDataKey.DAMAGE_TYPE26_1, StructuredDataKey.DAMAGE_TYPE1_21_11, damageType -> new DamageType(Either.left(damageType)));
container.replace(StructuredDataKey.PROVIDES_BANNER_PATTERNS26_1, StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5, patterns -> tagOrNull(patterns.patterns()));
container.replace(StructuredDataKey.DAMAGE_RESISTANT26_1, StructuredDataKey.DAMAGE_RESISTANT1_21_2, damageResistant -> new DamageResistant1_21_2(tagOrNull(damageResistant.types())));
container.replace(StructuredDataKey.BLOCKS_ATTACKS26_1, StructuredDataKey.BLOCKS_ATTACKS1_21_5, blocksAttacks -> {
if (blocksAttacks.bypassedBy() == null) {
return blocksAttacks;
}
// Remove bypassed by ids
return new BlocksAttacks(blocksAttacks.blockDelaySeconds(), blocksAttacks.disableCooldownScale(), blocksAttacks.damageReductions(), blocksAttacks.itemDamage(), null, blocksAttacks.blockSound(), blocksAttacks.disableSound());
});
container.remove(StructuredDataKey.ADDITIONAL_TRADE_COST);
container.remove(StructuredDataKey.DYE);
container.remove(StructuredDataKey.CAT_SOUND_VARIANT);
container.remove(StructuredDataKey.CHICKEN_SOUND_VARIANT);
container.remove(StructuredDataKey.COW_SOUND_VARIANT);
container.remove(StructuredDataKey.PIG_SOUND_VARIANT);
}
private static @Nullable Key tagOrNull(final HolderSet holderSet) {
return holderSet.hasTagKey() ? Key.of(holderSet.tagKey()) : null;
}
}
@@ -0,0 +1,41 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_21_11to26_1.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.Protocol1_21_11To26_1;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
public final class ComponentRewriter26_1 extends NBTComponentRewriter<ClientboundPacket1_21_11> {
public ComponentRewriter26_1(final Protocol1_21_11To26_1 protocol) {
super(protocol);
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
super.handleShowItem(connection, itemTag, componentsTag);
final int count = itemTag.getInt("count");
if (count == 0) {
itemTag.putInt("count", 1);
}
}
}
@@ -0,0 +1,122 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_21_11to26_1.rewriter;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
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.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.Protocol1_21_11To26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPackets1_21_11;
import com.viaversion.viaversion.rewriter.EntityRewriter;
public final class EntityPacketRewriter26_1 extends EntityRewriter<ClientboundPacket1_21_11, Protocol1_21_11To26_1> {
public EntityPacketRewriter26_1(final Protocol1_21_11To26_1 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
registerTrackerWithData1_21_9(ClientboundPackets1_21_11.ADD_ENTITY, EntityTypes1_21_11.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_11.SET_ENTITY_DATA);
registerRemoveEntities(ClientboundPackets1_21_11.REMOVE_ENTITIES);
registerPlayerAbilities(ClientboundPackets1_21_11.PLAYER_ABILITIES);
registerGameEvent(ClientboundPackets1_21_11.GAME_EVENT);
registerLogin1_20_5(ClientboundPackets1_21_11.LOGIN);
registerRespawn1_20_5(ClientboundPackets1_21_11.RESPAWN);
protocol.registerServerbound(ServerboundPackets26_1.INTERACT, wrapper -> {
final int entityId = wrapper.passthrough(Types.VAR_INT);
wrapper.write(Types.VAR_INT, 0); // Interact
final int hand = wrapper.passthrough(Types.VAR_INT);
final Vector3d location = wrapper.read(Types.LOW_PRECISION_VECTOR);
final boolean secondaryAction = wrapper.passthrough(Types.BOOLEAN);
// Send interact at as well
final PacketWrapper interactAtPacket = wrapper.create(ServerboundPackets1_21_6.INTERACT);
interactAtPacket.write(Types.VAR_INT, entityId);
interactAtPacket.write(Types.VAR_INT, 2); // Interact at
interactAtPacket.write(Types.FLOAT, (float) location.x());
interactAtPacket.write(Types.FLOAT, (float) location.y());
interactAtPacket.write(Types.FLOAT, (float) location.z());
interactAtPacket.write(Types.VAR_INT, hand);
interactAtPacket.write(Types.BOOLEAN, secondaryAction);
interactAtPacket.sendToServer(Protocol1_21_11To26_1.class);
});
protocol.registerServerbound(ServerboundPackets26_1.ATTACK, ServerboundPackets1_21_6.INTERACT, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.write(Types.VAR_INT, 1); // Attack
wrapper.write(Types.BOOLEAN, false); // Secondary action
});
protocol.registerServerbound(ServerboundPackets26_1.SPECTATE_ENTITY, ServerboundPackets1_21_6.INTERACT, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.write(Types.VAR_INT, 1); // Attack
wrapper.write(Types.BOOLEAN, true); // Secondary action
});
}
@Override
protected void registerRewrites() {
final EntityDataTypes26_1 entityDataTypes = protocol.mappedTypes().entityDataTypes();
filter().mapDataType(id -> {
int mappedId = id;
if (mappedId >= entityDataTypes.catSoundVariant.typeId()) {
mappedId++;
}
if (mappedId >= entityDataTypes.cowSoundVariant.typeId()) {
mappedId++;
}
if (mappedId >= entityDataTypes.pigSoundVariant.typeId()) {
mappedId++;
}
if (mappedId >= entityDataTypes.chickenSoundVariant.typeId()) {
mappedId++;
}
return entityDataTypes.byId(mappedId);
});
registerEntityDataTypeHandler(
entityDataTypes.itemType,
entityDataTypes.blockStateType,
entityDataTypes.optionalBlockStateType,
entityDataTypes.particleType,
entityDataTypes.particlesType,
entityDataTypes.componentType,
entityDataTypes.optionalComponentType
);
filter().type(EntityTypes1_21_11.VILLAGER).addIndex(19); // Is villager data finalized
filter().type(EntityTypes1_21_11.ZOMBIE_VILLAGER).addIndex(21); // Is villager data finalized
filter().type(EntityTypes1_21_11.ABSTRACT_AGEABLE).addIndex(17); // Age locked
}
@Override
public void onMappingDataLoaded() {
mapTypes();
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_21_11.getTypeFromId(type);
}
}
@@ -170,7 +170,7 @@ public final class Protocol1_21_2To1_21_4 extends AbstractProtocol<ClientboundPa
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));
VersionedTypes.V1_21_4.structuredData.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE1_20_5, StructuredDataKey.RARITY, StructuredDataKey.HIDE_TOOLTIP, StructuredDataKey.DAMAGE_RESISTANT,
StructuredDataKey.UNBREAKABLE1_20_5, StructuredDataKey.RARITY, StructuredDataKey.HIDE_TOOLTIP, StructuredDataKey.DAMAGE_RESISTANT1_21_2,
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS1_20_5, StructuredDataKey.CAN_PLACE_ON1_20_5,
StructuredDataKey.CAN_BREAK1_20_5, StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP,
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
@@ -194,9 +194,9 @@ public final class Protocol1_21_4To1_21_5 extends AbstractProtocol<ClientboundPa
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));
VersionedTypes.V1_21_5.structuredData.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT1_21_2,
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS1_21_5,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS, StructuredDataKey.PROVIDES_BANNER_PATTERNS,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS1_21_5, StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5,
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
StructuredDataKey.INTANGIBLE_PROJECTILE, StructuredDataKey.STORED_ENCHANTMENTS1_21_5, StructuredDataKey.DYED_COLOR1_21_5,
StructuredDataKey.MAP_COLOR, StructuredDataKey.MAP_ID, StructuredDataKey.MAP_DECORATIONS, StructuredDataKey.MAP_POST_PROCESSING,
@@ -216,8 +216,8 @@ public final class Protocol1_21_4To1_21_5 extends AbstractProtocol<ClientboundPa
StructuredDataKey.TROPICAL_FISH_BASE_COLOR, StructuredDataKey.TROPICAL_FISH_PATTERN_COLOR, StructuredDataKey.MOOSHROOM_VARIANT,
StructuredDataKey.RABBIT_VARIANT, StructuredDataKey.PIG_VARIANT, StructuredDataKey.FROG_VARIANT, StructuredDataKey.HORSE_VARIANT,
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT, StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_VARIANT,
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT, StructuredDataKey.WOLF_SOUND_VARIANT);
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT1_21_5, StructuredDataKey.WOLF_SOUND_VARIANT);
super.onMappingDataLoaded();
}
@@ -101,12 +101,12 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
StructuredDataKey.FOX_VARIANT, StructuredDataKey.SALMON_SIZE, StructuredDataKey.PARROT_VARIANT,
StructuredDataKey.TROPICAL_FISH_PATTERN, StructuredDataKey.TROPICAL_FISH_BASE_COLOR, StructuredDataKey.TROPICAL_FISH_PATTERN_COLOR,
StructuredDataKey.MOOSHROOM_VARIANT, StructuredDataKey.RABBIT_VARIANT, StructuredDataKey.COW_VARIANT,
StructuredDataKey.PIG_VARIANT, StructuredDataKey.CHICKEN_VARIANT, StructuredDataKey.FROG_VARIANT,
StructuredDataKey.PIG_VARIANT, StructuredDataKey.CHICKEN_VARIANT1_21_5, StructuredDataKey.FROG_VARIANT,
StructuredDataKey.HORSE_VARIANT, StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT,
StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_VARIANT, StructuredDataKey.CAT_COLLAR,
StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.BLOCKS_ATTACKS,
StructuredDataKey.PROVIDES_TRIM_MATERIAL, StructuredDataKey.BREAK_SOUND, StructuredDataKey.WOLF_SOUND_VARIANT,
StructuredDataKey.PROVIDES_BANNER_PATTERNS
StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.BLOCKS_ATTACKS1_21_5,
StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5, StructuredDataKey.BREAK_SOUND, StructuredDataKey.WOLF_SOUND_VARIANT,
StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5
);
private static final DataComponentMatchers EMPTY_DATA_MATCHERS = new DataComponentMatchers(new StructuredData[0], new DataComponentPredicate[0]);
private static final Heightmap[] EMPTY_HEIGHTMAPS = new Heightmap[0];
@@ -518,7 +518,7 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_8)) {
if (item.identifier() == 858 || item.identifier() == 863 || item.identifier() == 873 || item.identifier() == 868 || item.identifier() == 878) { // swords
item.dataContainer().remove(StructuredDataKey.CONSUMABLE1_21_2);
item.dataContainer().set(StructuredDataKey.BLOCKS_ATTACKS,
item.dataContainer().set(StructuredDataKey.BLOCKS_ATTACKS1_21_5,
new BlocksAttacks(
0F,
0F,
@@ -163,9 +163,9 @@ public final class Protocol1_21_5To1_21_6 extends AbstractProtocol<ClientboundPa
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));
VersionedTypes.V1_21_6.structuredData.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT1_21_2,
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS1_21_5,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS, StructuredDataKey.PROVIDES_BANNER_PATTERNS,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS1_21_5, StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5,
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
StructuredDataKey.INTANGIBLE_PROJECTILE, StructuredDataKey.STORED_ENCHANTMENTS1_21_5, StructuredDataKey.DYED_COLOR1_21_5,
StructuredDataKey.MAP_COLOR, StructuredDataKey.MAP_ID, StructuredDataKey.MAP_DECORATIONS, StructuredDataKey.MAP_POST_PROCESSING,
@@ -185,8 +185,8 @@ public final class Protocol1_21_5To1_21_6 extends AbstractProtocol<ClientboundPa
StructuredDataKey.TROPICAL_FISH_BASE_COLOR, StructuredDataKey.TROPICAL_FISH_PATTERN_COLOR, StructuredDataKey.MOOSHROOM_VARIANT,
StructuredDataKey.RABBIT_VARIANT, StructuredDataKey.PIG_VARIANT, StructuredDataKey.FROG_VARIANT, StructuredDataKey.HORSE_VARIANT,
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT, StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_VARIANT,
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT, StructuredDataKey.WOLF_SOUND_VARIANT);
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT1_21_5, StructuredDataKey.WOLF_SOUND_VARIANT);
super.onMappingDataLoaded();
}
@@ -174,9 +174,9 @@ public final class Protocol1_21_7To1_21_9 extends AbstractProtocol<ClientboundPa
.reader("flash", ParticleType.Readers.COLOR)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));
mappedTypes().structuredData.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT1_21_2,
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS1_21_5,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS, StructuredDataKey.PROVIDES_BANNER_PATTERNS,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS1_21_5, StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5,
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
StructuredDataKey.INTANGIBLE_PROJECTILE, StructuredDataKey.STORED_ENCHANTMENTS1_21_5, StructuredDataKey.DYED_COLOR1_21_5,
StructuredDataKey.MAP_COLOR, StructuredDataKey.MAP_ID, StructuredDataKey.MAP_DECORATIONS, StructuredDataKey.MAP_POST_PROCESSING,
@@ -196,8 +196,8 @@ public final class Protocol1_21_7To1_21_9 extends AbstractProtocol<ClientboundPa
StructuredDataKey.TROPICAL_FISH_BASE_COLOR, StructuredDataKey.TROPICAL_FISH_PATTERN_COLOR, StructuredDataKey.MOOSHROOM_VARIANT,
StructuredDataKey.RABBIT_VARIANT, StructuredDataKey.PIG_VARIANT, StructuredDataKey.FROG_VARIANT, StructuredDataKey.HORSE_VARIANT,
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT, StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_VARIANT,
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT, StructuredDataKey.WOLF_SOUND_VARIANT);
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT1_21_5, StructuredDataKey.WOLF_SOUND_VARIANT);
super.onMappingDataLoaded();
}
@@ -18,9 +18,10 @@
package com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_9to1_21_11.packet.ClientboundPacket1_21_11;
public enum ClientboundConfigurationPackets1_21_9 implements ClientboundPacket1_21_9, ClientboundPacket1_21_11 {
public enum ClientboundConfigurationPackets1_21_9 implements ClientboundPacket1_21_9, ClientboundPacket1_21_11, ClientboundPacket26_1 {
COOKIE_REQUEST, // 0x00
CUSTOM_PAYLOAD, // 0x01
@@ -18,8 +18,9 @@
package com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ServerboundPacket26_1;
public enum ServerboundConfigurationPackets1_21_9 implements ServerboundPacket1_21_9 {
public enum ServerboundConfigurationPackets1_21_9 implements ServerboundPacket1_21_9, ServerboundPacket26_1 {
CLIENT_INFORMATION, // 0x00
COOKIE_RESPONSE, // 0x01
@@ -58,7 +58,7 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.write(Types.MOVEMENT_VECTOR, Vector3d.ZERO); // Set at the end
wrapper.write(Types.LOW_PRECISION_VECTOR, Vector3d.ZERO); // Set at the end
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
@@ -70,12 +70,12 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
wrapper.set(Types.VAR_INT, 2, mappedBlockStateId);
}
wrapper.set(Types.MOVEMENT_VECTOR, 0, readRelativeMovement(wrapper));
wrapper.set(Types.LOW_PRECISION_VECTOR, 0, readRelativeMovement(wrapper));
});
protocol.registerClientbound(ClientboundPackets1_21_6.SET_ENTITY_MOTION, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.write(Types.MOVEMENT_VECTOR, readRelativeMovement(wrapper));
wrapper.write(Types.LOW_PRECISION_VECTOR, readRelativeMovement(wrapper));
});
protocol.registerClientbound(ClientboundPackets1_21_6.PLAYER_ROTATION, wrapper -> {
@@ -131,12 +131,11 @@ public final class Protocol1_21_9To1_21_11 extends AbstractProtocol<ClientboundP
tag.putString("skybox", "end");
attributes.putString("visual/fog_color", "#181318");
attributes.putString("visual/sky_color", "#000000");
attributes.putString("visual/sky_light_color", "#e580ff");
attributes.putString("visual/sky_light_color", "#ac60cd");
addAmbientCaveSound(attributes);
final CompoundTag backgroundMusic = new CompoundTag();
backgroundMusic.put("default", backgroundMusicEntry("music.game", false, 12000));
backgroundMusic.put("creative", backgroundMusicEntry("music.creative", false, 12000));
backgroundMusic.put("default", backgroundMusicEntry("music.end", true, 6000));
attributes.put("audio/background_music", backgroundMusic);
} else {
final ListTag<StringTag> timelines = new ListTag<>(List.of(new StringTag("day"), new StringTag("moon"), new StringTag("early_game")));
@@ -146,7 +145,8 @@ public final class Protocol1_21_9To1_21_11 extends AbstractProtocol<ClientboundP
addAmbientCaveSound(attributes);
final CompoundTag backgroundMusic = new CompoundTag();
backgroundMusic.put("default", backgroundMusicEntry("music.end", true, 6000));
backgroundMusic.put("default", backgroundMusicEntry("music.game", false, 12000));
backgroundMusic.put("creative", backgroundMusicEntry("music.creative", false, 12000));
attributes.put("audio/background_music", backgroundMusic);
}
@@ -323,9 +323,9 @@ public final class Protocol1_21_9To1_21_11 extends AbstractProtocol<ClientboundP
.reader("flash", ParticleType.Readers.COLOR)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));
mappedTypes().structuredData.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT,
StructuredDataKey.UNBREAKABLE1_21_5, StructuredDataKey.RARITY, StructuredDataKey.TOOLTIP_DISPLAY, StructuredDataKey.DAMAGE_RESISTANT1_21_2,
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS1_21_5,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS, StructuredDataKey.PROVIDES_BANNER_PATTERNS,
StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.BLOCKS_ATTACKS1_21_5, StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5,
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
StructuredDataKey.INTANGIBLE_PROJECTILE, StructuredDataKey.STORED_ENCHANTMENTS1_21_5, StructuredDataKey.DYED_COLOR1_21_5,
StructuredDataKey.MAP_COLOR, StructuredDataKey.MAP_ID, StructuredDataKey.MAP_DECORATIONS, StructuredDataKey.MAP_POST_PROCESSING,
@@ -345,10 +345,10 @@ public final class Protocol1_21_9To1_21_11 extends AbstractProtocol<ClientboundP
StructuredDataKey.TROPICAL_FISH_BASE_COLOR, StructuredDataKey.TROPICAL_FISH_PATTERN_COLOR, StructuredDataKey.MOOSHROOM_VARIANT,
StructuredDataKey.RABBIT_VARIANT, StructuredDataKey.PIG_VARIANT, StructuredDataKey.FROG_VARIANT, StructuredDataKey.HORSE_VARIANT,
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT, StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_VARIANT,
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT, StructuredDataKey.WOLF_SOUND_VARIANT,
StructuredDataKey.USE_EFFECTS, StructuredDataKey.MINIMUM_ATTACK_CHARGE, StructuredDataKey.DAMAGE_TYPE, StructuredDataKey.PIERCING_WEAPON,
StructuredDataKey.KINETIC_WEAPON, StructuredDataKey.SWING_ANIMATION, StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT);
StructuredDataKey.CAT_COLLAR, StructuredDataKey.SHEEP_COLOR, StructuredDataKey.SHULKER_COLOR, StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5,
StructuredDataKey.BREAK_SOUND, StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT1_21_5, StructuredDataKey.WOLF_SOUND_VARIANT,
StructuredDataKey.USE_EFFECTS, StructuredDataKey.MINIMUM_ATTACK_CHARGE, StructuredDataKey.DAMAGE_TYPE1_21_11, StructuredDataKey.PIERCING_WEAPON,
StructuredDataKey.KINETIC_WEAPON, StructuredDataKey.SWING_ANIMATION, StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT1_21_11);
super.onMappingDataLoaded();
}
@@ -122,10 +122,10 @@ public final class BlockItemPacketRewriter1_21_11 extends StructuredItemRewriter
container.remove(StructuredDataKey.SWING_ANIMATION);
container.remove(StructuredDataKey.KINETIC_WEAPON);
container.remove(StructuredDataKey.PIERCING_WEAPON);
container.remove(StructuredDataKey.DAMAGE_TYPE);
container.remove(StructuredDataKey.DAMAGE_TYPE1_21_11);
container.remove(StructuredDataKey.MINIMUM_ATTACK_CHARGE);
container.remove(StructuredDataKey.USE_EFFECTS);
container.remove(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT);
container.remove(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT1_21_11);
container.remove(StructuredDataKey.ATTACK_RANGE);
}
}
@@ -256,7 +256,7 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol<ClientboundPack
.reader("trail", ParticleType.Readers.TRAIL1_21_2)
.reader("item", ParticleType.Readers.item(VersionedTypes.V1_21_2.item));
VersionedTypes.V1_21_2.structuredData.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE1_20_5, StructuredDataKey.RARITY, StructuredDataKey.HIDE_TOOLTIP, StructuredDataKey.DAMAGE_RESISTANT,
StructuredDataKey.UNBREAKABLE1_20_5, StructuredDataKey.RARITY, StructuredDataKey.HIDE_TOOLTIP, StructuredDataKey.DAMAGE_RESISTANT1_21_2,
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS1_20_5, StructuredDataKey.CAN_PLACE_ON1_20_5,
StructuredDataKey.CAN_BREAK1_20_5, StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP,
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
@@ -39,7 +39,7 @@ import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2;
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.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_21_2;
@@ -572,7 +572,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
dataContainer.setEmpty(StructuredDataKey.V1_21_2.useRemainder);
});
dataContainer.replaceKey(StructuredDataKey.POTION_CONTENTS1_20_5, StructuredDataKey.POTION_CONTENTS1_21_2);
dataContainer.replace(StructuredDataKey.FIRE_RESISTANT, StructuredDataKey.DAMAGE_RESISTANT, fireResistant -> new DamageResistant(Key.of("minecraft:is_fire")));
dataContainer.replace(StructuredDataKey.FIRE_RESISTANT, StructuredDataKey.DAMAGE_RESISTANT1_21_2, fireResistant -> new DamageResistant1_21_2(Key.of("minecraft:is_fire")));
dataContainer.replace(StructuredDataKey.LOCK1_20_5, StructuredDataKey.LOCK1_21_2, tag -> {
final String lock = ((StringTag) tag).getValue();
final CompoundTag predicateTag = new CompoundTag();
@@ -639,7 +639,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
return trim;
});
dataContainer.replaceKey(StructuredDataKey.POTION_CONTENTS1_21_2, StructuredDataKey.POTION_CONTENTS1_20_5);
dataContainer.replace(StructuredDataKey.DAMAGE_RESISTANT, StructuredDataKey.FIRE_RESISTANT, damageResistant -> {
dataContainer.replace(StructuredDataKey.DAMAGE_RESISTANT1_21_2, StructuredDataKey.FIRE_RESISTANT, damageResistant -> {
if (damageResistant.typesTagKey().equals("is_fire")) {
return Unit.INSTANCE;
}
@@ -17,6 +17,7 @@
*/
package com.viaversion.viaversion.protocols.v1_8to1_9.rewriter;
import com.google.gson.JsonPrimitive;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.Via;
@@ -279,7 +280,7 @@ public class WorldPacketRewriter1_9 {
handler(wrapper -> {
for (int i = 0; i < 4; i++) {
final String line = wrapper.read(Types.STRING);
wrapper.write(Types.COMPONENT, ComponentUtil.plainToJson(line));
wrapper.write(Types.COMPONENT, new JsonPrimitive(line));
}
});
}
@@ -231,13 +231,20 @@ public class BlockRewriter<C extends ClientboundPacketType> {
}
public Chunk handleChunk1_19(PacketWrapper wrapper, ChunkTypeSupplier chunkTypeSupplier) {
return handleChunk1_19(wrapper, chunkTypeSupplier, null);
}
public Chunk handleChunk1_19(PacketWrapper wrapper, ChunkTypeSupplier chunkTypeSupplier, @Nullable ChunkTypeSupplier mappedChunkTypeSupplier) {
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
Preconditions.checkArgument(tracker.biomesSent() != -1, "Biome count not set");
Preconditions.checkArgument(tracker.currentWorldSectionHeight() != -1, "Section height not set");
final Type<Chunk> chunkType = chunkTypeSupplier.supply(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().mappedSize()),
MathUtil.ceilLog2(tracker.biomesSent()));
final Chunk chunk = wrapper.passthrough(chunkType);
final Type<Chunk> mappedChunkType = mappedChunkTypeSupplier != null ? mappedChunkTypeSupplier.supply(tracker.currentWorldSectionHeight(),
MathUtil.ceilLog2(protocol.getMappingData().getBlockStateMappings().mappedSize()),
MathUtil.ceilLog2(tracker.biomesSent())) : chunkType;
final Chunk chunk = wrapper.passthroughAndMap(chunkType, mappedChunkType);
for (final ChunkSection section : chunk.getSections()) {
final DataPalette blockPalette = section.palette(PaletteType.BLOCKS);
for (int i = 0; i < blockPalette.size(); i++) {
@@ -23,14 +23,18 @@ import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Abstract rewriter for the declare commands packet to handle argument type name and content changes.
*/
public class CommandRewriter<C extends ClientboundPacketType> {
private static final Set<String> REGISTRY_ARGUMENT_TYPES = Set.of("resource", "resource_key", "resource_or_tag", "resource_or_tag_key", "resource_selector");
protected final Protocol<C, ?, ?, ?> protocol;
protected final Map<String, CommandArgumentConsumer> parserHandlers = new HashMap<>();
@@ -130,10 +134,27 @@ public class CommandRewriter<C extends ClientboundPacketType> {
String newArgumentType = handleArgumentType(argumentType);
Preconditions.checkNotNull(newArgumentType, "No mapping for argument type %s", argumentType);
wrapper.write(Types.VAR_INT, mappedArgumentTypeId(newArgumentType));
// Always call the handler using the previous name
handleArgument(wrapper, argumentType);
boolean removedRegistryArgument = false;
if (protocol.getRegistryDataRewriter() != null && REGISTRY_ARGUMENT_TYPES.contains(Key.stripMinecraftNamespace(newArgumentType))) {
final String registry = wrapper.read(Types.STRING);
if (protocol.getRegistryDataRewriter().shouldRemoveRegistry(registry)) {
// Map removed registry arguments to a plain quotable string
removedRegistryArgument = true;
wrapper.write(Types.VAR_INT, mappedArgumentTypeId("brigadier:string"));
wrapper.write(Types.VAR_INT, 1);
} else {
// Keep reading
wrapper.write(Types.STRING, registry);
wrapper.rewindReader(1);
}
}
if (!removedRegistryArgument) {
wrapper.write(Types.VAR_INT, mappedArgumentTypeId(newArgumentType));
// Call the handler using the previous name
handleArgument(wrapper, argumentType);
}
if ((flags & 0x10) != 0) {
wrapper.passthrough(Types.STRING); // Suggestion type
@@ -321,7 +321,7 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
wrapper.passthrough(Types.MOVEMENT_VECTOR); // Movement
wrapper.passthrough(Types.LOW_PRECISION_VECTOR); // Movement
wrapper.passthrough(Types.BYTE); // Pitch
wrapper.passthrough(Types.BYTE); // Yaw
wrapper.passthrough(Types.BYTE); // Head yaw
@@ -50,6 +50,8 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
private final Type<Item[]> itemArrayType;
private final Type<Item[]> mappedItemArrayType;
private final Type<Item> itemCostType;
private final Type<Item> itemTemplateType;
private final Type<Item> mappedItemTemplateType;
private final Type<Item> mappedItemCostType;
private final Type<Item> optionalItemCostType;
private final Type<Item> mappedOptionalItemCostType;
@@ -62,6 +64,8 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
this.itemArrayType = types.itemArray();
this.mappedItemType = mappedTypes.item();
this.mappedItemArrayType = mappedTypes.itemArray();
this.itemTemplateType = types.itemTemplate();
this.mappedItemTemplateType = mappedTypes.itemTemplate();
this.itemCostType = types.itemCost();
this.mappedItemCostType = mappedTypes.itemCost();
this.optionalItemCostType = types.optionalItemCost();
@@ -74,6 +78,8 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
this.itemArrayType = itemArrayType;
this.mappedItemType = mappedItemType;
this.mappedItemArrayType = mappedItemArrayType;
this.itemTemplateType = null;
this.mappedItemTemplateType = null;
this.itemCostType = null;
this.mappedItemCostType = null;
this.optionalItemCostType = null;
@@ -120,6 +126,7 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
final ItemHasherBase itemHasher = itemHasher(connection);
final HashedItem originalHashedItem = itemHasher.originalHashedItem(customDataHash, item);
if (originalHashedItem != null) {
originalHashedItem.setAmount(item.amount());
return originalHashedItem;
}
}
@@ -480,7 +487,7 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
componentRewriter.processTag(wrapper.user(), description);
}
passthroughClientboundItem(wrapper); // Icon
passthroughClientboundItemTemplate(wrapper); // Icon
wrapper.passthrough(Types.VAR_INT); // Frame type
int flags = wrapper.passthrough(Types.INT); // Flags
if ((flags & 1) != 0) {
@@ -556,6 +563,12 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
wrapper.write(mappedItemType, item);
}
protected void passthroughClientboundItemTemplate(final PacketWrapper wrapper) {
// Uses the regular item type pre 26.1
final Item item = handleItemToClient(wrapper.user(), wrapper.read(itemTemplateType()));
wrapper.write(mappedItemTemplateType(), item);
}
protected void passthroughHashedItem(final PacketWrapper wrapper) {
final HashedItem item = handleHashedItem(wrapper.user(), wrapper.read(Types.HASHED_ITEM));
wrapper.write(Types.HASHED_ITEM, item);
@@ -616,4 +629,14 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
public Type<Item[]> mappedItemArrayType() {
return mappedItemArrayType;
}
@Override
public Type<Item> itemTemplateType() {
return itemTemplateType;
}
@Override
public Type<Item> mappedItemTemplateType() {
return mappedItemTemplateType;
}
}
@@ -228,9 +228,9 @@ public class ParticleRewriter<C extends ClientboundPacketType> implements com.vi
} else if (mappings.isItemParticle(id) && itemRewriter != null) {
final Particle.ParticleData<Item> data = particle.getArgument(0);
final Item item = itemRewriter.handleItemToClient(connection, data.getValue());
if (itemRewriter.mappedItemType() != null && itemRewriter.itemType() != itemRewriter.mappedItemType()) {
if (itemRewriter.mappedItemTemplateType() != null && itemRewriter.itemTemplateType() != itemRewriter.mappedItemTemplateType()) {
// Replace the type
particle.set(0, itemRewriter.mappedItemType(), item);
particle.set(0, itemRewriter.mappedItemTemplateType(), item);
} else {
data.setValue(item);
}
@@ -17,6 +17,7 @@
*/
package com.viaversion.viaversion.rewriter;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
@@ -24,13 +25,28 @@ import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import java.util.HashMap;
import java.util.Map;
// Base for 1.21.2 and onwards
public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
protected final Map<String, SlotDisplayConsumer> slotDisplayHandlers = new HashMap<>();
protected final Protocol<C, ?, ?, ?> protocol;
public RecipeDisplayRewriter(final Protocol<C, ?, ?, ?> protocol) {
this.protocol = protocol;
// empty and any_fuel are empty
slotDisplayHandlers.put("with_any_potion", this::handleSlotDisplay);
slotDisplayHandlers.put("only_with_component", this::handleOnlyWithComponentSlotDisplay);
slotDisplayHandlers.put("item", this::handleItemId);
slotDisplayHandlers.put("item_stack", this::handleItem);
slotDisplayHandlers.put("tag", wrapper -> wrapper.passthrough(Types.STRING));
slotDisplayHandlers.put("dye", this::handleDyeSlotDisplay);
slotDisplayHandlers.put("smithing_trim", this::handleSmithingTrimSlotDisplay);
slotDisplayHandlers.put("with_remainder", this::handleWithRemainderSlotDisplay);
slotDisplayHandlers.put("composite", this::handleSlotDisplayList);
}
public void registerUpdateRecipes(final C packetType) {
@@ -124,15 +140,21 @@ public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
}
protected void handleSlotDisplay(final PacketWrapper wrapper) {
// empty and any_fuel are empty
final int type = wrapper.passthrough(Types.VAR_INT);
switch (type) {
case 2 -> handleItemId(wrapper); // Item type
case 3 -> handleItem(wrapper); // Item
case 4 -> wrapper.passthrough(Types.STRING); // Tag key
case 5 -> handleSmithingTrimSlotDisplay(wrapper); // Smithing trim
case 6 -> handleWithRemainderSlotDisplay(wrapper); // With remainder
case 7 -> handleSlotDisplayList(wrapper); // Composite
final FullMappings mappings = protocol.getMappingData().getSlotDisplayMappings();
final int type = wrapper.read(Types.VAR_INT);
final int mappedType = mappings.getNewId(type);
if (mappedType == -1) {
// Write dummy
wrapper.write(Types.VAR_INT, 0);
return;
}
wrapper.write(Types.VAR_INT, mappedType);
final String identifier = mappings.identifier(type); // use the original type
final SlotDisplayConsumer handler = slotDisplayHandlers.get(Key.stripMinecraftNamespace(identifier));
if (handler != null) {
handler.accept(wrapper);
}
}
@@ -154,6 +176,17 @@ public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
handleSlotDisplay(wrapper); // Remainder
}
protected void handleOnlyWithComponentSlotDisplay(final PacketWrapper wrapper) {
handleSlotDisplay(wrapper); // Source
final int mappedDataComponentType = protocol.getMappingData().getDataComponentSerializerMappings().getNewIdOrDefault(wrapper.read(Types.VAR_INT), 0);
wrapper.write(Types.VAR_INT, mappedDataComponentType);
}
protected void handleDyeSlotDisplay(final PacketWrapper wrapper) {
handleSlotDisplay(wrapper); // Dye
handleSlotDisplay(wrapper); // Target
}
protected void handleIngredient(final PacketWrapper wrapper) {
final HolderSet items = wrapper.passthrough(Types.HOLDER_SET);
if (items.hasTagKey()) {
@@ -173,9 +206,9 @@ public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
protected void handleItem(final PacketWrapper wrapper) {
final ItemRewriter<?> itemRewriter = protocol.getItemRewriter();
final Item item = wrapper.read(itemRewriter.itemType());
final Item item = wrapper.read(itemRewriter.itemTemplateType());
itemRewriter.handleItemToClient(wrapper.user(), item);
wrapper.write(itemRewriter.mappedItemType(), item);
wrapper.write(itemRewriter.mappedItemTemplateType(), item);
}
protected int rewriteItemId(final int id) {
@@ -191,4 +224,10 @@ public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
ids[i] = rewriteItemId(id);
}
}
@FunctionalInterface
public interface SlotDisplayConsumer {
void accept(PacketWrapper wrapper);
}
}
@@ -353,6 +353,15 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
}
}
public RegistryEntry[] entriesFromTag(final CompoundTag tag) {
final RegistryEntry[] entries = new RegistryEntry[tag.size()];
int index = 0;
for (final Map.Entry<String, Tag> entry : tag.entrySet()) {
entries[index++] = new RegistryEntry(entry.getKey(), entry.getValue());
}
return entries;
}
@Override
public @Nullable KeyMappings getMappings(final String registryKey) {
return this.registryKeyMappings.get(Key.stripMinecraftNamespace(registryKey));
@@ -361,4 +370,9 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
public Map<String, KeyMappings> registryKeyMappings() {
return registryKeyMappings;
}
@Override
public boolean shouldRemoveRegistry(final String registryKey) {
return this.toRemove.contains(Key.stripMinecraftNamespace(registryKey));
}
}
@@ -67,7 +67,7 @@ public class StructuredItemRewriter<C extends ClientboundPacketType, S extends S
*/
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item.isEmpty()) {
if (Item.isEmpty(item)) {
return item;
}
@@ -128,7 +128,7 @@ public class StructuredItemRewriter<C extends ClientboundPacketType, S extends S
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item.isEmpty()) {
if (Item.isEmpty(item)) {
return item;
}
@@ -149,7 +149,7 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
for (int i = 0; i < length; i++) {
final String registryKey = wrapper.read(Types.STRING);
final String strippedKey = Key.stripMinecraftNamespace(registryKey);
if (toRemoveRegistries.contains(strippedKey)) {
if (shouldRemoveRegistry(strippedKey)) {
finalLength--;
final int tagsSize = wrapper.read(Types.VAR_INT);
@@ -282,6 +282,14 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
return toAdd.computeIfAbsent(tagType, type -> new ArrayList<>());
}
public boolean shouldRemoveRegistry(final String registryKey) {
if (protocol.getRegistryDataRewriter() != null
&& protocol.getRegistryDataRewriter().shouldRemoveRegistry(registryKey)) {
return true;
}
return toRemoveRegistries.contains(registryKey);
}
public @Nullable IdRewriteFunction getRewriter(RegistryType tagType) {
MappingData mappingData = protocol.getMappingData();
return switch (tagType) {
@@ -289,7 +297,7 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
case ITEM -> mappingData != null && mappingData.getItemMappings() != null ? mappingData::getNewItemId : null;
case ENTITY -> protocol.getEntityRewriter() != null ? id -> protocol.getEntityRewriter().newEntityId(id) : null;
case ENCHANTMENT -> mappingData != null && mappingData.getEnchantmentMappings() != null ? id -> mappingData.getEnchantmentMappings().getNewId(id) : null;
case FLUID, GAME_EVENT -> null;
case FLUID, GAME_EVENT, DAMAGE_TYPE, BANNER_PATTERN -> null;
};
}
}
Loaded 100 of 109 files, more files were not shown because too many files have changed in this diff. Show more