Compare commits

..
Author SHA1 Message Date
Nassim Jahnke 366f08d951 Separate Fabric platform on modrinth
... or it'll fail when specifying versions below 1.14
2026-10-08 16:05:13 +02:00
Nassim Jahnke d628f09334 5.12.1 Release 2026-10-08 15:41:05 +02:00
Nassim JahnkeandWhiteProject1 6fecd58773 Check full type length if possible
Closes #5104

Co-authored-by: WhiteProject1 <Odunyasi167@gmail.com>
2026-10-08 15:38:29 +02:00
冰砚炽andNassim Jahnke da7619c82d Fix custom enchantment value_check predicate is not rewritten for 26.3 clients (#5101)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-10-08 15:12:20 +02:00
Nassim Jahnke b83268efa0 Update deps 2026-10-08 11:02:33 +02:00
Florian Reuth 309c3e57c1 Remove map number tag again in 1.16.4->1.17 (#5099) 2026-10-04 08:55:53 +02:00
Florian Reuth 34a445efcd Copy mutable item before updating in 1.20.3->1.20.5 (#5102) 2026-10-04 08:54:12 +02:00
Florian Reuth 3a949d70eb Don't error on invalid filtered pages in 1.20.2->1.20.3 (#5098) 2026-10-02 14:55:26 +02:00
Rocco 99bfa389b4 Fix backwards conversion of new 1.20.5 trim patterns (#5078) 2026-10-01 19:07:09 +02:00
Florian Reuth 327d4739f5 Fix HIDE_ADDITIONAL_TOOLTIP disappearing in 1.21.4->1.21.5 (#5092) 2026-10-01 18:43:08 +02:00
Florian Reuth 3a7a8e06a8 Backup & restore map color in 26.2->26.3 (#5096) 2026-10-01 15:06:47 +02:00
Florian Reuth 85db19200f Upgrade empty swing animation as well in 26.2->26.3 (#5097) 2026-10-01 15:03:49 +02:00
Florian Reuth 226609b864 Don't lose bypassed_by tag key in 1.21.11->26.1 (#5095) 2026-09-30 20:56:50 +02:00
Florian Reuth 7049f7eaf1 Fix bees not spawning after creative mode in 1.21.7->1.21.9 (#5094) 2026-09-30 20:55:49 +02:00
Florian Reuth a062d0905b Don't use random unique id for attribute conversion in 1.20.5->1.21 (#5093) 2026-09-30 08:43:07 +02:00
Florian Reuth 7ac58c104b Fix Consumable animation hashing between 1.21.5 and 1.21.11 (#5087) 2026-09-29 18:37:42 +02:00
Florian Reuth 7a6e838eb1 Inline damage type for 1.21.11 (#5090) 2026-09-29 18:37:24 +02:00
Florian Reuth 57bc53346c Fix sulfur_cube_content network type (#5091) 2026-09-29 16:03:05 +02:00
terbin 3df7c76c8c Add statistic mappings for 1.16.2->1.17 (#5089) 2026-09-29 14:46:34 +02:00
Florian Reuth 3f35005051 Fix default-count item template hashing (#5088) 2026-09-29 14:17:24 +02:00
Florian Reuth f9d21e073b Fix conditional hashing of a bunch of item data components (#5082) 2026-09-29 14:12:08 +02:00
Florian Reuth e813796d9a Handle remaining components in registry data (#5077) 2026-09-28 19:31:54 +02:00
Florian Reuth 271b6e7ff7 Fix splash potion sounds not playing in 26.2->26.3 (#5076) 2026-09-28 19:30:57 +02:00
LeonTG 7bf4a30075 Fix ender dragon having the wrong dragon phase in 1.8->1.9 (#5070) 2026-09-28 08:55:09 +02:00
PolangandFlorian Reuth 414e978829 Skip removal markers in 1.20.5+ item cost type (#5073)
Co-authored-by: Florian Reuth <git@florianreuth.de>
2026-09-28 08:45:15 +02:00
Nassim Jahnke 637a81e569 Handle dripstone particles dimension attribute registry data
Fixes #5074
2026-09-27 14:21:22 +02:00
Florian Reuth b4023127f6 Force set health back >0 in 1.19.1->1.19.3 (#5061) 2026-09-20 14:54:56 +02:00
Nassim Jahnke 46a61058dd Add missing tags across protocols, reduce stored tags size 2026-09-20 13:06:35 +02:00
Nassim Jahnke 66b90a5b2a Add missing tag for newly placed solid blocks letting through rain
Fixes #5060
2026-09-20 11:59:58 +02:00
Florian Reuth 8f03d6bcef Cancel axe stripping for pre 1.13, shovel dirth paths for pre 1.9 (#5057) 2026-09-20 09:44:19 +02:00
75 changed files with 647 additions and 342 deletions

No files matched your search

+3 -3
View File
@@ -15,12 +15,12 @@ jobs:
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6.3.0
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v5.7.0
uses: actions/setup-java@v6.0.1
with:
distribution: 'temurin'
java-version: 17
@@ -30,7 +30,7 @@ jobs:
- name: Upload Artifacts to GitHub
# Only upload on the preview repository as there is no CI job for it.
if: ${{ github.repository == 'ViaVersion/ViaVersionDev' && github.ref_name == 'preview' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: Artifacts
path: build/libs/
+2 -2
View File
@@ -20,12 +20,12 @@ jobs:
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6.3.0
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v5.7.0
uses: actions/setup-java@v6.0.1
with:
distribution: 'temurin'
java-version: 17
@@ -26,6 +26,8 @@ import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.function.IntConsumer;
@@ -49,6 +51,12 @@ public final class IdRanges {
return ids;
}
public static IntList decodeAsList(final ByteArrayTag rangesTag) {
final IntList ids = new IntArrayList();
forEachId(rangesTag, ids::add);
return ids;
}
public static void forEachId(final ByteArrayTag rangesTag, final IntConsumer consumer) {
final ByteBuf buf = Unpooled.wrappedBuffer(rangesTag.getValue());
int prevEnd = 0;
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.ListTag;
@@ -198,8 +199,14 @@ public class MappingDataBase implements MappingData {
final List<TagData> tagsList = new ArrayList<>(tags.size());
for (final Map.Entry<String, Tag> entry : tag.entrySet()) {
final IntArrayTag entries = (IntArrayTag) entry.getValue();
tagsList.add(new TagData(entry.getKey(), entries.getValue()));
final int[] entries;
if (entry.getValue() instanceof final ByteArrayTag rangesTag) {
entries = IdRanges.decodeAsList(rangesTag).toIntArray();
} else {
// Old format / if the values need to be sorted
entries = ((IntArrayTag) entry.getValue()).getValue();
}
tagsList.add(new TagData(entry.getKey(), entries));
}
this.tags.put(type, tagsList);
@@ -79,8 +79,8 @@ public record PaintingVariant(int width, int height, String assetId, @Nullable T
.write("width", Types.INT, value.width())
.write("height", Types.INT, value.height())
.write("asset_id", Types.IDENTIFIER, Key.of(value.assetId()))
.writeOptional("title", Types.TRUSTED_TAG, value.title())
.writeOptional("author", Types.TRUSTED_TAG, value.author()));
.writeOptional("title", Types.TEXT_COMPONENT_TAG, value.title())
.writeOptional("author", Types.TEXT_COMPONENT_TAG, value.author()));
}
@Override
@@ -55,7 +55,6 @@ import com.viaversion.viaversion.api.minecraft.item.data.CookingFuel;
import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
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;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
@@ -125,7 +124,7 @@ 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_TYPE1_21_11 = new StructuredDataKey<>("damage_type", DamageType.TYPE1_21_11);
public static final StructuredDataKey<Either<Integer, String>> DAMAGE_TYPE1_21_11 = new StructuredDataKey<>("damage_type", new SynchronizedRegistryEitherType(RegistryKey.of("damage_type")));
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);
@@ -153,6 +152,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_21);
public static final StructuredDataKey<FoodProperties1_21_2> FOOD1_21_2 = new StructuredDataKey<>("food", FoodProperties1_21_2.TYPE);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE1_21_2);
// 1.21.5-1.21.9 only, animation id 5 was still named spear
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_5 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE1_21_5);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE26_3 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE26_3);
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);
@@ -32,6 +32,6 @@ public class StructuredDataKeys26_2 extends StructuredDataKeys1_21_11 {
public StructuredDataKeys26_2(final VersionedTypesHolder types) {
super(types);
this.sulfurCubeContent = add("sulfur_cube_content", types.item());
this.sulfurCubeContent = add("sulfur_cube_content", types.itemTemplate());
}
}
@@ -1,126 +0,0 @@
/*
* 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.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData.MappingType;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
// TODO move block state provider rewriting to registry data rewriter
public record BlockTransformData(CompoundTag blockStateProvider, Holder<SoundEvent> sound, int transformParticle,
int[] disallowedFaces, @Nullable String loot, int dropStrategy,
boolean updateFromNeighbors, int transformType,
boolean consumeOnUse, int itemDamagePerUse) implements Rewritable, Copyable {
public static final Type<BlockTransformData> TYPE = new Type<>(BlockTransformData.class) {
@Override
public BlockTransformData read(final ByteBuf buffer) {
final CompoundTag blockStateProvider = Types.COMPOUND_TAG.read(buffer);
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
final int transformParticle = Types.VAR_INT.readPrimitive(buffer);
final int[] disallowedFaces = Types.VAR_INT_ARRAY_PRIMITIVE.read(buffer);
final String loot = Types.OPTIONAL_STRING.read(buffer);
final int dropStrategy = Types.VAR_INT.readPrimitive(buffer);
final boolean updateFromNeighbors = Types.BOOLEAN.read(buffer);
final int transformType = Types.VAR_INT.readPrimitive(buffer);
final boolean consumeOnUse = Types.BOOLEAN.read(buffer);
final int itemDamagePerUse = Types.VAR_INT.readPrimitive(buffer);
return new BlockTransformData(blockStateProvider, sound, transformParticle, disallowedFaces, loot, dropStrategy, updateFromNeighbors, transformType, consumeOnUse, itemDamagePerUse);
}
@Override
public void write(final ByteBuf buffer, final BlockTransformData value) {
Types.COMPOUND_TAG.write(buffer, value.blockStateProvider);
Types.SOUND_EVENT.write(buffer, value.sound);
Types.VAR_INT.writePrimitive(buffer, value.transformParticle);
Types.VAR_INT_ARRAY_PRIMITIVE.write(buffer, value.disallowedFaces);
Types.OPTIONAL_STRING.write(buffer, value.loot);
Types.VAR_INT.writePrimitive(buffer, value.dropStrategy);
Types.BOOLEAN.write(buffer, value.updateFromNeighbors);
Types.VAR_INT.writePrimitive(buffer, value.transformType);
Types.BOOLEAN.write(buffer, value.consumeOnUse);
Types.VAR_INT.writePrimitive(buffer, value.itemDamagePerUse);
}
@Override
public void write(final Ops ops, final BlockTransformData data) {
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingType.SOUND, "intentionally_empty"));
ops.writeMap(map -> map
.write("block_state_provider", Types.COMPOUND_TAG, data.blockStateProvider)
.writeOptional("sound", Types.SOUND_EVENT, data.sound, defaultSound)
.writeOptional("particle", EnumTypes.TRANSFORM_PARTICLE, data.transformParticle, 0)
.writeOptional("disallowed_faces", EnumTypes.DIRECTION.new EnumArrayType(), data.disallowedFaces, new int[0])
.writeOptional("loot", Types.STRING, data.loot)
.writeOptional("drop_strategy", Types.VAR_INT, data.dropStrategy, 1)
.writeOptional("update_from_neighbors", Types.BOOLEAN, data.updateFromNeighbors, true)
.writeOptional("transform_type", Types.VAR_INT, data.transformType, 0)
.writeOptional("consume_on_use", Types.BOOLEAN, data.consumeOnUse, true)
.writeOptional("item_damage_per_use", Types.VAR_INT, data.itemDamagePerUse, 0)
);
}
};
public static final ArrayType<BlockTransformData> ARRAY_TYPE = new ArrayType<>(TYPE);
@Override
public BlockTransformData rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
CompoundTag updatedTag = blockStateProvider().copy();
if (protocol.getRegistryDataRewriter().updateBlockStateProvider(updatedTag)) {
// Back it up clientbound so server data doesn't disappear; remove it for newly spawned items serverbound.
// Given it's not even encoded properly over the network and would otherwise require keeping full block state mappings
// and is not needed on the client, we only do the bare minimum to guarantee compatibility.
if (clientbound) {
updatedTag.put("backup", this.blockStateProvider);
} else {
final CompoundTag backupTag = updatedTag.getCompoundTag("backup");
updatedTag = backupTag != null ? backupTag : dummyBlockStateProvider();
}
}
return new BlockTransformData(updatedTag, sound, transformParticle, disallowedFaces, loot, dropStrategy, updateFromNeighbors, transformType, consumeOnUse, itemDamagePerUse);
}
private CompoundTag dummyBlockStateProvider() {
final CompoundTag state = new CompoundTag();
state.putString("Name", "dirt");
final CompoundTag tag = new CompoundTag();
tag.putString("type", "simple");
tag.put("state", state);
return tag;
}
@Override
public BlockTransformData copy() {
return new BlockTransformData(blockStateProvider.copy(), sound, transformParticle, disallowedFaces, loot, dropStrategy, updateFromNeighbors, transformType, consumeOnUse, itemDamagePerUse);
}
}
@@ -1,39 +0,0 @@
/*
* 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.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
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> TYPE1_21_11 = TransformingType.of(new EitherType<>(Types.VAR_INT, Types.STRING), DamageType.class, DamageType::new, DamageType::id);
}
@@ -33,13 +33,13 @@ public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyab
public static final Type<DeathProtection> TYPE1_21_2 = new TransformingType<>(ConsumeEffect.ARRAY_TYPE1_21_2, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
@Override
public void write(final Ops ops, final DeathProtection value) {
ops.writeMap(map -> map.write("death_effects", ConsumeEffect.ARRAY_TYPE1_21_2, value.deathEffects));
ops.writeMap(map -> map.writeOptional("death_effects", ConsumeEffect.ARRAY_TYPE1_21_2, value.deathEffects, new ConsumeEffect<?>[0]));
}
};
public static final Type<DeathProtection> TYPE26_3 = new TransformingType<>(ConsumeEffect.ARRAY_TYPE26_3, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
@Override
public void write(final Ops ops, final DeathProtection value) {
ops.writeMap(map -> map.write("death_effects", ConsumeEffect.ARRAY_TYPE26_3, value.deathEffects));
ops.writeMap(map -> map.writeOptional("death_effects", ConsumeEffect.ARRAY_TYPE26_3, value.deathEffects, new ConsumeEffect<?>[0]));
}
};
@@ -47,11 +47,8 @@ public final class EnumTypes {
public static final EnumType AXOLOTL_VARIANT = new EnumType("lucy", "wild", "gold", "cyan", "blue");
public static final EnumType EQUIPMENT_SLOT = new EnumType("mainhand", "feet", "legs", "chest", "head", "offhand", "body", "saddle");
public static final EnumType SWING_ANIMATION1_21_11 = new EnumType("none", "whack", "stab");
public static final EnumType ITEM_USE_ANIMATION1_21_5 = new EnumType("none", "eat", "drink", "block", "bow", "spear", "crossbow", "spyglass", "toot_horn", "brush", "bundle");
public static final EnumType ITEM_USE_ANIMATION = new EnumType("none", "eat", "drink", "block", "bow", "trident", "crossbow", "spyglass", "toot_horn", "brush", "bundle", "spear");
public static final EnumType DIRECTION = new EnumType("down", "up", "north", "south", "west", "east");
public static final EnumType TRANSFORM_PARTICLE = new EnumType("none", "scrape", "wax_on", "wax_off");
public static final EnumType TRAMNSFORM_DROP_STRATEGY = new EnumType("clicked_face", "from_middle");
public static final EnumType TRAMNSFORM_TYPE = new EnumType("single_block", "copper_chest");
// Enums with non-ordinal ids
public static final FakeEnumType RABBIT_VARIANT = new FakeEnumType(List.of("brown", "white", "black", "white_splotched", "gold", "salt"), of(99, "evil"));
// Hardcoded registries
@@ -34,7 +34,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public final class FilterableComponent extends Filterable<Tag> implements Copyable, Rewritable {
public static final Type<FilterableComponent> TYPE = new FilterableType<>(Types.TAG, Types.OPTIONAL_TAG, FilterableComponent.class) {
public static final Type<FilterableComponent> TYPE = new FilterableType<>(Types.TEXT_COMPONENT_TAG, Types.OPTIONAL_TAG, FilterableComponent.class) {
@Override
protected FilterableComponent create(final Tag raw, final Tag filtered) {
return new FilterableComponent(raw, filtered);
@@ -67,7 +67,7 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
.write("sound_event", Types.SOUND_EVENT, value.soundEvent())
.write("use_duration", Types.FLOAT, value.useDuration())
.write("range", Types.FLOAT, value.range())
.write("description", Types.TAG, value.description()));
.write("description", Types.TEXT_COMPONENT_TAG, value.description()));
}
@Override
@@ -103,8 +103,8 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
.write("sound_event", Types.SOUND_EVENT, value.soundEvent())
.write("use_duration", Types.FLOAT, value.useDuration())
.write("range", Types.FLOAT, value.range())
.write("durability_damage", Types.VAR_INT, value.durabilityDamage())
.write("description", Types.TAG, value.description()));
.writeOptional("durability_damage", Types.VAR_INT, value.durabilityDamage(), 0)
.write("description", Types.TEXT_COMPONENT_TAG, value.description()));
}
@Override
@@ -29,16 +29,19 @@ 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.util.Copyable;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Rewritable;
public record PotDecorations1_20_5(int[] itemIds) implements Copyable, Rewritable {
private static final Key BRICK = Key.ofPath("brick");
public static final Type<PotDecorations1_20_5> TYPE = new TransformingType<>(Types.VAR_INT_ARRAY_PRIMITIVE, PotDecorations1_20_5.class, PotDecorations1_20_5::new, PotDecorations1_20_5::itemIds) {
@Override
public void write(final Ops ops, final PotDecorations1_20_5 value) {
// Vanilla always encodes all 4 sides, filling missing ones with bricks
ops.writeList(list -> {
for (final int itemId : value.itemIds) {
list.write(Types.IDENTIFIER, ops.context().registryAccess().item(itemId));
for (int i = 0; i < 4; i++) {
list.write(Types.IDENTIFIER, i < value.itemIds.length ? ops.context().registryAccess().item(value.itemIds[i]) : BRICK);
}
});
}
@@ -52,10 +52,10 @@ public record SignText(Tag[] messages, Tag @Nullable [] filteredMessages, int co
@Override
public void write(final Ops ops, final SignText value) {
ops.writeMap(map -> map
.write("messages", Types.SIGN_TEXT, value.messages)
.writeOptional("filtered_messages", Types.SIGN_TEXT, value.filteredMessages)
.write("color", Types.VAR_INT, value.color, 15)
.write("has_glowing_text", Types.BOOLEAN, value.hasGlowingText, false));
.write("messages", Types.TEXT_COMPONENT_TAG_ARRAY, value.messages)
.writeOptional("filtered_messages", Types.TEXT_COMPONENT_TAG_ARRAY, value.filteredMessages)
.write("color", EnumTypes.DYE_COLOR, value.color)
.write("has_glowing_text", Types.BOOLEAN, value.hasGlowingText));
}
};
}
@@ -31,6 +31,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.EnumTypes;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.EnumType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
@@ -39,16 +40,19 @@ public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<S
boolean hasConsumeParticles,
ConsumeEffect<?>[] consumeEffects) implements Copyable, Rewritable {
public static final Type<Consumable1_21_2> TYPE1_21_2 = new ConsumableType(ConsumeEffect.ARRAY_TYPE1_21_2);
public static final Type<Consumable1_21_2> TYPE26_3 = new ConsumableType(ConsumeEffect.ARRAY_TYPE26_3);
public static final Type<Consumable1_21_2> TYPE1_21_2 = new ConsumableType(ConsumeEffect.ARRAY_TYPE1_21_2, EnumTypes.ITEM_USE_ANIMATION);
public static final Type<Consumable1_21_2> TYPE1_21_5 = new ConsumableType(ConsumeEffect.ARRAY_TYPE1_21_2, EnumTypes.ITEM_USE_ANIMATION1_21_5);
public static final Type<Consumable1_21_2> TYPE26_3 = new ConsumableType(ConsumeEffect.ARRAY_TYPE26_3, EnumTypes.ITEM_USE_ANIMATION);
private static final class ConsumableType extends Type<Consumable1_21_2> {
private final Type<ConsumeEffect<?>[]> consumeEffectType;
private final EnumType animationType;
private ConsumableType(final Type<ConsumeEffect<?>[]> consumeEffectType) {
private ConsumableType(final Type<ConsumeEffect<?>[]> consumeEffectType, final EnumType animationType) {
super(Consumable1_21_2.class);
this.consumeEffectType = consumeEffectType;
this.animationType = animationType;
}
@Override
@@ -75,7 +79,7 @@ public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<S
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "entity.generic.eat"));
ops.writeMap(map -> map
.writeOptional("consume_seconds", Types.FLOAT, value.consumeSeconds, 1.6F)
.writeOptional("animation", EnumTypes.ITEM_USE_ANIMATION, value.animationType, 1)
.writeOptional("animation", animationType, value.animationType, 1)
.writeOptional("sound", Types.SOUND_EVENT, value.sound, defaultSound)
.writeOptional("has_consume_particles", Types.BOOLEAN, value.hasConsumeParticles, true)
.writeOptional("on_consume_effects", consumeEffectType, value.consumeEffects, new ConsumeEffect<?>[0]));
@@ -56,7 +56,7 @@ public record ConsumeEffect<T>(int id, Type<T> type, T value) {
@Override
public void write(final Ops ops, final Float value) {
ops.writeMap(map -> map.write("diameter", Types.FLOAT, value, 16F));
ops.writeMap(map -> map.writeOptional("diameter", Types.FLOAT, value, 16F));
}
};
public static final Type<TeleportRandomlyConsumeEffect> TELEPORT_RANDOMLY_TYPE26_3 = new Type<>(TeleportRandomlyConsumeEffect.class) {
@@ -76,8 +76,8 @@ public record ConsumeEffect<T>(int id, Type<T> type, T value) {
@Override
public void write(final Ops ops, final TeleportRandomlyConsumeEffect value) {
ops.writeMap(map -> map
.write("diameter", Types.FLOAT, value.diameter(), 16F)
.write("directional_particles", Types.BOOLEAN, value.directionalParticles(), true)
.writeOptional("diameter", Types.FLOAT, value.diameter(), 16F)
.writeOptional("directional_particles", Types.BOOLEAN, value.directionalParticles(), true)
);
}
};
@@ -227,6 +227,7 @@ public final class Types {
public static final Type<Tag[]> TAG_ARRAY = new ArrayType<>(TAG);
public static final Type<Tag> OPTIONAL_TAG = TagType.OptionalTagType.type();
public static final Type<Tag> TEXT_COMPONENT_TAG = new TextComponentTagType(); // only strictly needed for hashing
public static final Type<Tag[]> TEXT_COMPONENT_TAG_ARRAY = new ArrayType<>(Types.TEXT_COMPONENT_TAG);
public static final Type<Tag> CUSTOM_CLICK_ACTION_TAG = new LengthPrefixedTagType(65536);
public static final FixedLengthArrayType<Tag> SIGN_TEXT = new FixedLengthArrayType<>(TAG, 4);
@@ -111,4 +111,14 @@ public class ArrayType<T> extends Type<T[]> {
public ArrayType<T> withMaxLength(final int maxLength) {
return new ArrayType<>(this.getOutputClass(), this.elementType, maxLength);
}
static int checkLength(final int length, final int elementBytes, final int readable) {
if (length < 0) {
throw new IllegalArgumentException("Length " + length + " is negative");
}
if ((long) length * elementBytes > readable) {
throw new IllegalArgumentException("Length " + length + " is larger than readable bytes");
}
return length;
}
}
@@ -57,7 +57,7 @@ public class BooleanArrayType extends Type<boolean[]> {
@Override
public boolean[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
Preconditions.checkArgument(buffer.isReadable(length), "Length is larger than readable bytes");
final boolean[] array = new boolean[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readBoolean();
@@ -56,7 +56,7 @@ public class ByteArrayType extends Type<byte[]> {
@Override
public byte[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
Preconditions.checkArgument(buffer.isReadable(length), "Length is larger than readable bytes");
final byte[] array = new byte[length];
buffer.readBytes(array);
return array;
@@ -27,6 +27,8 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import static com.viaversion.viaversion.api.type.types.ArrayType.checkLength;
public class FloatArrayType extends Type<float[]> {
private final int length;
@@ -55,8 +57,7 @@ public class FloatArrayType extends Type<float[]> {
@Override
public float[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final int length = checkLength(this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length, Float.BYTES, buffer.readableBytes());
final float[] array = new float[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readFloat();
@@ -28,6 +28,8 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import static com.viaversion.viaversion.api.type.types.ArrayType.checkLength;
public class IntArrayType extends Type<int[]> {
private final int length;
@@ -56,8 +58,7 @@ public class IntArrayType extends Type<int[]> {
@Override
public int[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final int length = checkLength(this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length, Integer.BYTES, buffer.readableBytes());
final int[] array = new int[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readInt();
@@ -28,6 +28,8 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import static com.viaversion.viaversion.api.type.types.ArrayType.checkLength;
public class LongArrayType extends Type<long[]> {
private final int length;
@@ -43,8 +45,7 @@ public class LongArrayType extends Type<long[]> {
@Override
public long[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final int length = checkLength(this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length, Long.BYTES, buffer.readableBytes());
return readFixedLength(buffer, length);
}
@@ -34,7 +34,6 @@ import io.netty.buffer.ByteBuf;
// Very similar to normal items (and just results in an item), except it allows non-positive amounts and has id/amount swapped because ???
public final class ItemCostType1_20_5 extends Type<Item> {
private static final StructuredData<?>[] EMPTY_DATA_ARRAY = new StructuredData[0];
private final Type<StructuredData<?>[]> dataArrayType;
public ItemCostType1_20_5(final Type<StructuredData<?>[]> dataArrayType) {
@@ -54,7 +53,8 @@ public final class ItemCostType1_20_5 extends Type<Item> {
public void write(final ByteBuf buffer, final Item object) {
Types.VAR_INT.writePrimitive(buffer, object.identifier());
Types.VAR_INT.writePrimitive(buffer, object.amount());
dataArrayType.write(buffer, object.dataContainer().data().values().toArray(EMPTY_DATA_ARRAY));
// Item costs are exact-match predicates without removal markers, so empty data can't be written
dataArrayType.write(buffer, object.dataContainer().data().values().stream().filter(StructuredData::isPresent).toArray(StructuredData[]::new));
}
public static final class OptionalItemCostType extends OptionalType<Item> {
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types.item;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
@@ -55,6 +56,16 @@ public class ItemTemplateType26_1 extends ItemType1_20_5 {
writeData(buffer, object);
}
@Override
public void write(final Ops ops, final Item item) {
// Unlike item stacks, templates omit the default count
ops.writeMap(map -> {
map.write("id", Types.IDENTIFIER, ops.context().registryAccess().item(item.identifier()))
.writeOptional("count", Types.VAR_INT, item.amount(), 1);
writeComponents(map, item);
});
}
public static final class OptionalItemTemplateType extends OptionalType<Item> {
public OptionalItemTemplateType(final Type<Item> type) {
@@ -127,22 +127,25 @@ public class ItemType1_20_5 extends Type<Item> {
ops.writeMap(map -> {
map.write("id", Types.IDENTIFIER, ops.context().registryAccess().item(item.identifier()))
.write("count", Types.VAR_INT, item.amount());
writeComponents(map, item);
});
}
if (item.dataContainer().isEmpty()) {
return;
}
protected void writeComponents(final Ops.MapSerializer map, final Item item) {
if (item.dataContainer().isEmpty()) {
return;
}
map.writeMap("components", components -> {
for (final StructuredData<?> data : item.dataContainer().data().values()) {
String key = Key.namespaced(data.key().identifier());
if (data.isEmpty()) {
key = "!" + key;
}
//noinspection unchecked
components.write(key, (Type<StructuredData<?>>) dataType, data);
map.writeMap("components", components -> {
for (final StructuredData<?> data : item.dataContainer().data().values()) {
String key = Key.namespaced(data.key().identifier());
if (data.isEmpty()) {
key = "!" + key;
}
});
//noinspection unchecked
components.write(key, (Type<StructuredData<?>>) dataType, data);
}
});
}
@@ -31,7 +31,6 @@ 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_TYPE1_21_11
));
public CodecRegistryContext(final Protocol<?, ?, ?, ?> protocol, final RegistryAccess registryAccess, final boolean mapped) {
@@ -125,6 +125,7 @@ public final class ItemPacketRewriter1_17 extends ItemRewriter<ClientboundPacket
}
if (tag.getNumberTag("map") == null) {
tag.put("map", new IntTag(0));
tag.putBoolean(nbtTagName("map"), true);
}
}
@@ -132,4 +133,20 @@ public final class ItemPacketRewriter1_17 extends ItemRewriter<ClientboundPacket
return item;
}
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) return null;
super.handleItemToServer(connection, item);
CompoundTag tag = item.tag();
if (item.identifier() == 733 && tag != null && tag.remove(nbtTagName("map")) != null) {
tag.remove("map");
if (tag.isEmpty()) {
item.setTag(null);
}
}
return item;
}
}
@@ -51,6 +51,7 @@ import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.rewriter.ComponentRew
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.rewriter.EntityPacketRewriter1_19_3;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.rewriter.ItemPacketRewriter1_19_3;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.storage.NonceStorage1_19_3;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.storage.PlayerHealthStorage;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.storage.ReceivedMessagesStorage;
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPackets1_19_1;
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ServerboundPackets1_19_1;
@@ -380,6 +381,7 @@ public final class Protocol1_19_1To1_19_3 extends AbstractProtocol<ClientboundPa
@Override
public void init(final UserConnection user) {
user.put(new ReceivedMessagesStorage());
user.put(new PlayerHealthStorage());
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_19_3.PLAYER));
}
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.api.type.types.version.Types1_19;
import com.viaversion.viaversion.api.type.types.version.Types1_19_3;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.Protocol1_19_1To1_19_3;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.storage.PlayerHealthStorage;
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPackets1_19_1;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import java.util.BitSet;
@@ -75,6 +76,13 @@ public final class EntityPacketRewriter1_19_3 extends EntityRewriter<Clientbound
}
});
protocol.registerClientbound(ClientboundPackets1_19_1.SET_HEALTH, wrapper -> {
final float health = wrapper.passthrough(Types.FLOAT);
final int food = wrapper.passthrough(Types.VAR_INT);
final float saturation = wrapper.passthrough(Types.FLOAT);
wrapper.user().get(PlayerHealthStorage.class).update(health, food, saturation);
});
protocol.registerClientbound(ClientboundPackets1_19_1.RESPAWN, new PacketHandlers() {
@Override
public void register() {
@@ -94,6 +102,18 @@ public final class EntityPacketRewriter1_19_3 extends EntityRewriter<Clientbound
}
wrapper.write(Types.BYTE, keepDataMask);
});
handler(wrapper -> {
final PlayerHealthStorage healthStorage = wrapper.user().get(PlayerHealthStorage.class);
if (healthStorage.dead()) {
// The client takes over the entity data of the dead player, its health of 0 would instantly re-open the death screen
final PacketWrapper setHealth = wrapper.create(ClientboundPackets1_19_3.SET_HEALTH);
setHealth.write(Types.FLOAT, 20F); // Overwritten by the server right after the respawn
setHealth.write(Types.VAR_INT, healthStorage.food());
setHealth.write(Types.FLOAT, healthStorage.saturation());
setHealth.send(Protocol1_19_1To1_19_3.class);
healthStorage.setDead(false);
}
});
}
});
@@ -0,0 +1,49 @@
/*
* 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_19_1to1_19_3.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
public final class PlayerHealthStorage implements StorableObject {
private boolean dead;
private int food;
private float saturation;
public void update(final float health, final int food, final float saturation) {
this.dead = health <= 0;
this.food = food;
this.saturation = saturation;
}
public boolean dead() {
return this.dead;
}
public void setDead(final boolean dead) {
this.dead = dead;
}
public int food() {
return this.food;
}
public float saturation() {
return this.saturation;
}
}
@@ -137,7 +137,10 @@ public final class BlockItemPacketRewriter1_20_3 extends ItemRewriter<Clientboun
final CompoundTag filteredPages = tag.getCompoundTag("filtered_pages");
if (filteredPages != null) {
for (final String string : filteredPages.keySet()) {
updatePageTag(filteredPages.getStringTag(string));
final StringTag pageTag = filteredPages.getStringTag(string);
if (pageTag != null) {
updatePageTag(pageTag);
}
}
}
}
@@ -692,6 +692,11 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
if (bannerPatterns != null) {
restoreBannerPatternsFromBackup(bannerPatterns, data);
}
final CompoundTag trim = backupTag.getCompoundTag("trim");
if (trim != null) {
restoreArmorTrimFromBackup(trim, data);
}
}
private void restoreInstrumentFromBackup(final CompoundTag instrument, final StructuredDataContainer data) {
@@ -799,6 +804,25 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
data.set(StructuredDataKey.BANNER_PATTERNS, patternLayer.toArray(new BannerPatternLayer[0]));
}
private void restoreArmorTrimFromBackup(final CompoundTag trim, final StructuredDataContainer data) {
final Tag materialTag = trim.get("material");
final Holder<ArmorTrimMaterial1_20_5> materialHolder;
if (materialTag instanceof IntTag materialIntTag) {
materialHolder = Holder.of(materialIntTag.asInt());
} else if (materialTag instanceof CompoundTag materialCompoundTag) {
ArmorTrimMaterial1_20_5 material = readTrimMaterial(materialCompoundTag);
if (material == null) {
return;
}
materialHolder = Holder.of(material);
} else return;
final Holder<ArmorTrimPattern> patternHolder = Holder.of(trim.getInt("pattern"));
final boolean showInTooltip = trim.getBoolean("show_in_tooltip");
data.set(StructuredDataKey.TRIM1_20_5, new ArmorTrim1_20_5(materialHolder, patternHolder, showInTooltip));
}
private AdventureModePredicate updateBlockPredicates(final UserConnection connection, final ListTag<StringTag> tag, final boolean showInTooltip) {
final BlockPredicate[] predicates = tag.stream()
.map(StringTag::getValue)
@@ -969,8 +993,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
private void updateArmorTrim(final UserConnection connection, final StructuredDataContainer data, final CompoundTag trimTag, final boolean showInTooltip) {
final Tag materialTag = trimTag.get("material");
final Holder<ArmorTrimMaterial1_20_5> materialHolder;
final ProtocolStorables1_20_5 storables = connection.storables(protocol);
final ArmorTrimStorage trimStorage = storables.armorTrims();
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
if (materialTag instanceof StringTag materialStringTag) {
final int id = trimStorage.trimMaterials().keyToId(materialStringTag.getValue());
if (id == -1) {
@@ -979,39 +1002,11 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
materialHolder = Holder.of(id);
} else if (materialTag instanceof CompoundTag materialCompoundTag) {
final StringTag assetNameTag = materialCompoundTag.getStringTag("asset_name");
final StringTag ingredientTag = materialCompoundTag.getStringTag("ingredient");
if (assetNameTag == null || ingredientTag == null) {
ArmorTrimMaterial1_20_5 material = readTrimMaterial(materialCompoundTag);
if (material == null) {
return;
}
final int ingredientId = StructuredDataConverter.removeItemBackupTag(materialCompoundTag, toMappedItemId(ingredientTag.getValue()));
if (ingredientId == -1) {
return;
}
final NumberTag itemModelIndexTag = materialCompoundTag.getNumberTag("item_model_index");
final CompoundTag overrideArmorMaterialsTag = materialCompoundTag.getCompoundTag("override_armor_materials");
final Tag descriptionTag = materialCompoundTag.get("description");
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
if (overrideArmorMaterialsTag != null) {
for (final Map.Entry<String, Tag> entry : overrideArmorMaterialsTag.entrySet()) {
if (!(entry.getValue() instanceof StringTag valueTag)) {
continue;
}
overrideArmorMaterials.put(entry.getKey(), valueTag.getValue());
}
}
materialHolder = Holder.of(new ArmorTrimMaterial1_20_5(
assetNameTag.getValue(),
ingredientId,
itemModelIndexTag != null ? itemModelIndexTag.asFloat() : 0,
overrideArmorMaterials,
descriptionTag
));
materialHolder = Holder.of(material);
} else return;
final Tag patternTag = trimTag.get("pattern");
@@ -1048,6 +1043,42 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
data.set(StructuredDataKey.TRIM1_20_5, new ArmorTrim1_20_5(materialHolder, patternHolder, showInTooltip));
}
private ArmorTrimMaterial1_20_5 readTrimMaterial(final CompoundTag tag) {
final StringTag assetNameTag = tag.getStringTag("asset_name");
final StringTag ingredientTag = tag.getStringTag("ingredient");
if (assetNameTag == null || ingredientTag == null) {
return null;
}
final int ingredientId = StructuredDataConverter.removeItemBackupTag(tag, toMappedItemId(ingredientTag.getValue()));
if (ingredientId == -1) {
return null;
}
final NumberTag itemModelIndexTag = tag.getNumberTag("item_model_index");
final CompoundTag overrideArmorMaterialsTag = tag.getCompoundTag("override_armor_materials");
final Tag descriptionTag = tag.get("description");
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
if (overrideArmorMaterialsTag != null) {
for (final Map.Entry<String, Tag> entry : overrideArmorMaterialsTag.entrySet()) {
if (!(entry.getValue() instanceof StringTag valueTag)) {
continue;
}
overrideArmorMaterials.put(entry.getKey(), valueTag.getValue());
}
}
return new ArmorTrimMaterial1_20_5(
assetNameTag.getValue(),
ingredientId,
itemModelIndexTag != null ? itemModelIndexTag.asFloat() : 0,
overrideArmorMaterials,
descriptionTag
);
}
private void updateMobTags(final StructuredDataContainer data, final CompoundTag tag) {
final CompoundTag bucketEntityData = new CompoundTag();
for (final String mobTagKey : MOB_TAGS) {
@@ -1235,7 +1266,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
if (itemsTag != null) {
final Item[] items = itemsTag.stream()
.limit(256)
.map(item -> itemFromTag(connection, item))
.map(item -> itemFromTag(connection, item.copy()))
.filter(item -> !item.isEmpty())
.toArray(Item[]::new);
data.set(dataKey, items);
@@ -551,10 +551,22 @@ public final class StructuredDataConverter {
} else {
final String oldKey = trimStorage.trimPatterns().idToKey(data.pattern().id());
if (oldKey != null) {
trimTag.putString("pattern", oldKey);
if (!"flow".equals(oldKey) && !"bolt".equals(oldKey)) {
trimTag.putString("pattern", oldKey);
} else if (backupInconvertibleData) {
final CompoundTag backupTrim = trimTag.copy();
if (!data.material().isDirect()) {
backupTrim.putInt("material", data.material().id());
}
backupTrim.putInt("pattern", data.pattern().id());
backupTrim.putBoolean("show_in_tooltip", data.showInTooltip());
getBackupTag(tag).put("trim", backupTrim);
}
}
}
tag.put("Trim", trimTag);
if (trimTag.contains("material") && trimTag.contains("pattern")) {
tag.put("Trim", trimTag);
}
if (!data.showInTooltip()) {
putHideFlag(tag, HIDE_ARMOR_TRIM);
}
@@ -55,6 +55,7 @@ import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.UUIDUtil;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.UUID;
@@ -183,7 +184,7 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
}
uuid = UUIDUtil.parseUUID(Key.stripNamespace(id).toUpperCase(Locale.ROOT));
return uuid != null ? uuid : UUIDUtil.randomUUID();
return uuid != null ? uuid : UUID.nameUUIDFromBytes(id.getBytes(StandardCharsets.UTF_8));
}
@Override
@@ -215,9 +216,10 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
tagRewriter.addEmptyTags(RegistryType.ENTITY, "minecraft:can_turn_in_boats", "minecraft:deflects_projectiles", "minecraft:immune_to_infested",
"minecraft:immune_to_oozing", "minecraft:no_anger_from_wind_charge");
tagRewriter.addTag(RegistryType.ENCHANTMENT, "minecraft:curse", 10, 41); // Binding and vanishing curse
tagRewriter.addTag(RegistryType.ENCHANTMENT, "minecraft:prevents_decorated_pot_shattering", 21); // Silk touch
// Add other enchantment tags empty
tagRewriter.addEmptyTags(RegistryType.ENCHANTMENT, "double_trade_price", "in_enchanting_table", "non_treasure", "on_mob_spawn_equipment", "on_random_loot",
"on_traded_equipment", "prevents_bee_spawns_when_mining", "prevents_decorated_pot_shattering", "prevents_ice_melting", "prevents_infested_spawns", "smelts_loot",
"on_traded_equipment", "prevents_bee_spawns_when_mining", "prevents_ice_melting", "prevents_infested_spawns", "smelts_loot",
"tooltip_order", "tradeable", "treasure", "exclusive_set/armor", "exclusive_set/boots", "exclusive_set/bow", "exclusive_set/crossbow", "exclusive_set/damage",
"exclusive_set/mining", "exclusive_set/riptide");
}
@@ -33,7 +33,6 @@ 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.trim.ProvidesTrimMaterial1_20_5;
@@ -86,7 +85,7 @@ public final class BlockItemPacketRewriter26_1 extends StructuredItemRewriter<Cl
container.replace(StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5, StructuredDataKey.PROVIDES_TRIM_MATERIAL26_1, providesTrimMaterial -> upgradeHolder(protocol, connection, providesTrimMaterial.material(), "trim_material"));
container.replace(StructuredDataKey.CHICKEN_VARIANT1_21_5, StructuredDataKey.CHICKEN_VARIANT26_1, chickenVariant -> upgradeEitherVariant(protocol, connection, chickenVariant, "chicken_variant"));
container.replace(StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT1_21_11, StructuredDataKey.ZOMBIE_NAUTILUS_VARIANT26_1, nautilusVariant -> upgradeEitherVariant(protocol, connection, nautilusVariant, "zombie_nautilus_variant"));
container.replace(StructuredDataKey.DAMAGE_TYPE1_21_11, StructuredDataKey.DAMAGE_TYPE26_1, damageType -> upgradeEitherVariant(protocol, connection, damageType.id(), "damage_type"));
container.replace(StructuredDataKey.DAMAGE_TYPE1_21_11, StructuredDataKey.DAMAGE_TYPE26_1, damageType -> upgradeEitherVariant(protocol, connection, damageType, "damage_type"));
container.replace(StructuredDataKey.PROVIDES_BANNER_PATTERNS1_21_5, StructuredDataKey.PROVIDES_BANNER_PATTERNS26_1, key -> new ProvidesBannerPatterns(tagKeyToHolderSet(protocol, connection, "banner_pattern", key.original())));
container.replace(StructuredDataKey.DAMAGE_RESISTANT1_21_2, StructuredDataKey.DAMAGE_RESISTANT26_1, damageResistant -> new DamageResistant26_1(tagKeyToHolderSet(protocol, connection, "damage_type", damageResistant.typesTagKey().original())));
container.replaceKey(StructuredDataKey.BLOCKS_ATTACKS1_21_5, StructuredDataKey.BLOCKS_ATTACKS26_1);
@@ -137,14 +136,14 @@ public final class BlockItemPacketRewriter26_1 extends StructuredItemRewriter<Cl
container.replace(StructuredDataKey.PROVIDES_TRIM_MATERIAL26_1, StructuredDataKey.PROVIDES_TRIM_MATERIAL1_21_5, providesTrimMaterial -> new ProvidesTrimMaterial1_20_5(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.DAMAGE_TYPE26_1, StructuredDataKey.DAMAGE_TYPE1_21_11, Either::left);
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 -> {
final Key key = tagOrNull(damageResistant.types());
return key != null ? new DamageResistant1_21_2(key) : null;
});
container.replace(StructuredDataKey.BLOCKS_ATTACKS26_1, StructuredDataKey.BLOCKS_ATTACKS1_21_5, blocksAttacks -> {
if (blocksAttacks.bypassedBy() == null) {
if (blocksAttacks.bypassedBy() == null || blocksAttacks.bypassedBy().hasTagKey()) {
return blocksAttacks;
}
// Remove bypassed by ids
@@ -22,6 +22,7 @@ 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.Holder;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_5;
@@ -181,7 +182,7 @@ public final class Protocol1_21_4To1_21_5 extends AbstractProtocol<ClientboundPa
StructuredDataKey.POT_DECORATIONS1_20_5, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_21_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_5,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_5,
StructuredDataKey.USE_COOLDOWN, StructuredDataKey.DAMAGE, StructuredDataKey.EQUIPPABLE1_21_5, StructuredDataKey.ITEM_MODEL,
StructuredDataKey.GLIDER, StructuredDataKey.TOOLTIP_STYLE, StructuredDataKey.DEATH_PROTECTION1_21_2, StructuredDataKey.WEAPON,
StructuredDataKey.POTION_DURATION_SCALE, StructuredDataKey.VILLAGER_VARIANT, StructuredDataKey.WOLF_VARIANT, StructuredDataKey.WOLF_COLLAR,
@@ -191,6 +192,9 @@ public final class Protocol1_21_4To1_21_5 extends AbstractProtocol<ClientboundPa
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT, StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_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);
tagRewriter.renameTag(RegistryType.BLOCK, "dead_bush_may_place_on", "dry_vegetation_may_place_on");
super.onMappingDataLoaded();
}
@@ -302,6 +302,7 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
final StructuredDataContainer dataContainer = item.dataContainer();
dataContainer.replaceKey(StructuredDataKey.TOOL1_20_5, StructuredDataKey.TOOL1_21_5);
dataContainer.replaceKey(StructuredDataKey.EQUIPPABLE1_21_2, StructuredDataKey.EQUIPPABLE1_21_5);
dataContainer.replaceKey(StructuredDataKey.CONSUMABLE1_21_2, StructuredDataKey.CONSUMABLE1_21_5);
dataContainer.replace(StructuredDataKey.INSTRUMENT1_21_2, StructuredDataKey.INSTRUMENT1_21_5, EitherHolder::of);
// Collect hidden tooltips
@@ -408,6 +409,7 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
final StructuredDataContainer dataContainer = item.dataContainer();
dataContainer.replaceKey(StructuredDataKey.TOOL1_21_5, StructuredDataKey.TOOL1_20_5);
dataContainer.replaceKey(StructuredDataKey.EQUIPPABLE1_21_5, StructuredDataKey.EQUIPPABLE1_21_2);
dataContainer.replaceKey(StructuredDataKey.CONSUMABLE1_21_5, StructuredDataKey.CONSUMABLE1_21_2);
dataContainer.replace(StructuredDataKey.INSTRUMENT1_21_5, StructuredDataKey.INSTRUMENT1_21_2, instrument -> instrument.hasHolder() ? instrument.holder() : null);
final TooltipDisplay tooltipDisplay = dataContainer.get(StructuredDataKey.TOOLTIP_DISPLAY);
@@ -417,7 +419,8 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
}
final FullMappings mappings = Protocol1_21_4To1_21_5.MAPPINGS.getDataComponentSerializerMappings();
if (tooltipDisplay.hiddenComponents().containsAll(HIDE_ADDITIONAL_KEYS.stream().map(key -> mappings.id(key.identifier())).toList())) {
// Components added in 1.21.5 don't have an id here and have already been dropped from the hidden set
if (tooltipDisplay.hiddenComponents().containsAll(HIDE_ADDITIONAL_KEYS.stream().map(key -> mappings.id(key.identifier())).filter(id -> id != -1).toList())) {
dataContainer.set(StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP);
}
}
@@ -478,7 +481,7 @@ public final class BlockItemPacketRewriter1_21_5 extends StructuredItemRewriter<
final ProtocolVersion serverVersion = connection.getProtocolInfo().serverProtocolVersion();
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().remove(StructuredDataKey.CONSUMABLE1_21_5);
item.dataContainer().set(StructuredDataKey.BLOCKS_ATTACKS1_21_5,
new BlocksAttacks(
0F,
@@ -21,6 +21,7 @@ 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.GameMode;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_6;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
@@ -131,7 +132,7 @@ public final class Protocol1_21_5To1_21_6 extends AbstractProtocol<ClientboundPa
StructuredDataKey.POT_DECORATIONS1_20_5, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_21_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_6,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_5,
StructuredDataKey.USE_COOLDOWN, StructuredDataKey.DAMAGE, StructuredDataKey.EQUIPPABLE1_21_6, StructuredDataKey.ITEM_MODEL,
StructuredDataKey.GLIDER, StructuredDataKey.TOOLTIP_STYLE, StructuredDataKey.DEATH_PROTECTION1_21_2, StructuredDataKey.WEAPON,
StructuredDataKey.POTION_DURATION_SCALE, StructuredDataKey.VILLAGER_VARIANT, StructuredDataKey.WOLF_VARIANT, StructuredDataKey.WOLF_COLLAR,
@@ -141,6 +142,9 @@ public final class Protocol1_21_5To1_21_6 extends AbstractProtocol<ClientboundPa
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.LLAMA_VARIANT, StructuredDataKey.AXOLOTL_VARIANT, StructuredDataKey.CAT_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);
tagRewriter.renameTag(RegistryType.BLOCK, "plays_ambient_desert_block_sounds", "triggers_ambient_desert_dry_vegetation_block_sounds");
super.onMappingDataLoaded();
}
@@ -155,7 +155,7 @@ public final class Protocol1_21_7To1_21_9 extends AbstractProtocol<ClientboundPa
StructuredDataKey.POT_DECORATIONS1_20_5, 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_PLAYABLE1_21_5, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_6,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_5,
StructuredDataKey.USE_COOLDOWN, StructuredDataKey.DAMAGE, StructuredDataKey.EQUIPPABLE1_21_6, StructuredDataKey.ITEM_MODEL,
StructuredDataKey.GLIDER, StructuredDataKey.TOOLTIP_STYLE, StructuredDataKey.DEATH_PROTECTION1_21_2, StructuredDataKey.WEAPON,
StructuredDataKey.POTION_DURATION_SCALE, StructuredDataKey.VILLAGER_VARIANT, StructuredDataKey.WOLF_VARIANT, StructuredDataKey.WOLF_COLLAR,
@@ -81,7 +81,13 @@ public final class BlockItemPacketRewriter1_21_9 extends StructuredItemRewriter<
}
public static void downgradeData(final Item item, final StructuredDataContainer container) {
container.replaceKey(StructuredDataKey.BEES1_21_9, StructuredDataKey.BEES1_20_5);
container.replace(StructuredDataKey.BEES1_21_9, StructuredDataKey.BEES1_20_5, bees -> {
for (final Bee bee : bees) {
// Stripped from the tag since 1.21.9 but required to load the entity before
bee.entityData().tag().putString("id", "minecraft:bee");
}
return bees;
});
container.replace(StructuredDataKey.ENTITY_DATA1_21_9, StructuredDataKey.ENTITY_DATA1_20_5, entityData -> {
final String id = Protocol1_21_7To1_21_9.MAPPINGS.getEntityMappings().identifier(entityData.type());
entityData.tag().putString("id", id);
@@ -89,9 +89,11 @@ public final class BlockItemPacketRewriter1_21_11 extends StructuredItemRewriter
}
public static void upgradeData(final Item item, final StructuredDataContainer container) {
container.replaceKey(StructuredDataKey.CONSUMABLE1_21_5, StructuredDataKey.CONSUMABLE1_21_2);
}
public static void downgradeData(final Item item, final StructuredDataContainer container) {
container.replaceKey(StructuredDataKey.CONSUMABLE1_21_2, StructuredDataKey.CONSUMABLE1_21_5);
container.remove(StructuredDataKey.SWING_ANIMATION);
container.remove(StructuredDataKey.KINETIC_WEAPON);
container.remove(StructuredDataKey.PIERCING_WEAPON);
@@ -216,6 +216,11 @@ public class SpawnPacketRewriter1_9 {
int entityID = wrapper.get(Types.VAR_INT, 0);
EntityTracker1_9 tracker = wrapper.user().getEntityTracker(protocol);
tracker.handleEntityData(entityID, entityDataList);
// dragon default phase on 1.9+ is 10 (hovering), so we set it to match the only phase 1.8 had, which was 0 (circling)
if (tracker.entityType(entityID) == EntityTypes1_9.EntityType.ENDER_DRAGON) {
entityDataList.add(new EntityData(11, EntityDataTypes1_9.VAR_INT, 0)); // 11 = dragon phase id
}
});
}
});
@@ -17,10 +17,14 @@
*/
package com.viaversion.viaversion.protocols.v26_2to26_3;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.HolderSet;
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.StructuredDataKeys26_2;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys26_3;
@@ -67,6 +71,36 @@ import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
public final class Protocol26_2To26_3 extends AbstractProtocol<ClientboundPacket26_1, ClientboundPacket26_3, ServerboundPacket26_1, ServerboundPacket26_3> {
public static final MappingData26_3 MAPPINGS = new MappingData26_3();
private static final int SPLASH_POTION_SOUND = 1053;
private static final int INSTANT_SPLASH_POTION_SOUND = 1054;
private static final int SPLASH_POTION_PARTICLES = 2002;
private static final int INSTANT_SPLASH_POTION_PARTICLES = 2007;
private static final String[] POT_PATTERNS = {
"angler",
"archer",
"arms_up",
"blade",
"brewer",
"burn",
"danger",
"explorer",
"flow",
"friend",
"guster",
"heart",
"heartbreak",
"howl",
"miner",
"mourner",
"plenty",
"prize",
"scrape",
"sheaf",
"shelter",
"skull",
"snort"
};
private final EntityPacketRewriter26_3 entityRewriter = new EntityPacketRewriter26_3(this);
private final BlockItemPacketRewriter26_3 itemRewriter = new BlockItemPacketRewriter26_3(this);
private final BlockRewriter<ClientboundPacket26_1> blockRewriter = new BlockPacketRewriter26_3(this);
@@ -98,7 +132,14 @@ public final class Protocol26_2To26_3 extends AbstractProtocol<ClientboundPacket
appendClientbound(ClientboundConfigurationPackets1_21_9.FINISH_CONFIGURATION, wrapper -> {
final PacketWrapper clocksPacket = wrapper.create(ClientboundConfigurationPackets26_3.REGISTRY_DATA);
clocksPacket.write(Types.STRING, "decorated_pot_pattern");
clocksPacket.write(Types.REGISTRY_ENTRY_ARRAY, MAPPINGS.potPatterns());
final RegistryEntry[] entries = new RegistryEntry[POT_PATTERNS.length];
for (int i = 0; i < POT_PATTERNS.length; i++) {
final String key = POT_PATTERNS[i];
final CompoundTag tag = new CompoundTag();
tag.putString("asset_id", key + "_pottery_pattern");
entries[i] = new RegistryEntry(key, tag);
}
clocksPacket.write(Types.REGISTRY_ENTRY_ARRAY, entries);
clocksPacket.send(Protocol26_2To26_3.class);
final PacketWrapper blockTransformersPacket = wrapper.create(ClientboundConfigurationPackets26_3.REGISTRY_DATA);
@@ -137,6 +178,27 @@ public final class Protocol26_2To26_3 extends AbstractProtocol<ClientboundPacket
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TRUSTED_OPTIONAL_TAG)); // Target Name
});
// 26.3 plays the potion splash sound through its own level event, older clients played it together with the particles
appendClientbound(ClientboundPackets26_1.LEVEL_EVENT, wrapper -> {
final int id = wrapper.get(Types.INT, 0);
final BlockPosition position = wrapper.get(Types.BLOCK_POSITION1_14, 0);
final int soundId;
if (id == SPLASH_POTION_PARTICLES) {
soundId = SPLASH_POTION_SOUND;
} else if (id == INSTANT_SPLASH_POTION_PARTICLES) {
soundId = INSTANT_SPLASH_POTION_SOUND;
} else {
return;
}
final PacketWrapper soundPacket = wrapper.create(ClientboundPackets26_3.LEVEL_EVENT);
soundPacket.write(Types.INT, soundId);
soundPacket.write(Types.BLOCK_POSITION1_14, position);
soundPacket.write(Types.INT, 0); // Data
soundPacket.write(Types.BOOLEAN, false); // Global
soundPacket.scheduleSend(Protocol26_2To26_3.class);
});
// 26.3 reads the items the brewing stand slots accept from the server, older clients have them hardcoded
appendClientbound(ClientboundPackets26_1.UPDATE_RECIPES, wrapper -> {
wrapper.resetReader();
@@ -186,6 +248,9 @@ public final class Protocol26_2To26_3 extends AbstractProtocol<ClientboundPacket
StructuredDataKey.PROVIDES_POTTERY_PATTERN, StructuredDataKey.BLOCK_TRANSFORMER, StructuredDataKey.COMPOSTABLE, StructuredDataKey.VILLAGER_FOOD,
StructuredDataKey.COOKING_FUEL, StructuredDataKey.BREWING_FUEL, StructuredDataKey.MOB_VISIBILITY, StructuredDataKey.SIGN_TEXT_BACK, StructuredDataKey.SIGN_TEXT_FRONT,
StructuredDataKey.WAXED, StructuredDataKey.CUSHION_COLOR, StructuredDataKey.ATTACK_ANIMATION, StructuredDataKey.INTERACT_ANIMATION);
tagRewriter.renameTag(RegistryType.BLOCK, "convertable_to_mud", "convertible_to_mud");
super.onMappingDataLoaded();
}
@@ -20,15 +20,16 @@ package com.viaversion.viaversion.protocols.v26_2to26_3.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import java.util.Arrays;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
public final class MappingData26_3 extends MappingDataBase {
private static final String[] BREWING_INPUTS = {
"potion",
"splash_potion",
"lingering_potion"
"lingering_potion",
"glass_bottle"
};
private static final String[] BREWING_REAGENTS = {
"blaze_powder",
@@ -53,31 +54,6 @@ public final class MappingData26_3 extends MappingDataBase {
"sugar",
"turtle_helmet"
};
private static final String[] POT_PATTERNS = {
"angler",
"archer",
"arms_up",
"blade",
"brewer",
"burn",
"danger",
"explorer",
"flow",
"friend",
"guster",
"heart",
"heartbreak",
"howl",
"miner",
"mourner",
"plenty",
"prize",
"scrape",
"sheaf",
"shelter",
"skull",
"snort"
};
private CompoundTag blockTransformerRegistry;
private int[] brewingInputIds;
@@ -91,25 +67,25 @@ public final class MappingData26_3 extends MappingDataBase {
protected void loadExtras(final CompoundTag data) {
blockTransformerRegistry = MappingDataLoader.INSTANCE.loadNBTFromFile("block-transformer-registry-26.3.nbt");
brewingInputIds = Arrays.stream(BREWING_INPUTS).mapToInt(identifier -> this.getFullItemMappings().mappedId(identifier)).toArray();
brewingReagentIds = Arrays.stream(BREWING_REAGENTS).mapToInt(identifier -> this.getFullItemMappings().mappedId(identifier)).toArray();
brewingInputIds = itemIds(BREWING_INPUTS);
brewingReagentIds = itemIds(BREWING_REAGENTS);
}
private int[] itemIds(final String[] identifiers) {
final IntList ids = new IntArrayList(identifiers.length);
for (final String identifier : identifiers) {
final int id = getFullItemMappings().mappedId(identifier);
if (id != -1) {
ids.add(id);
}
}
return ids.toIntArray();
}
public CompoundTag blockTransformerRegistry() {
return blockTransformerRegistry;
}
public RegistryEntry[] potPatterns() {
final RegistryEntry[] entries = new RegistryEntry[POT_PATTERNS.length];
for (int i = 0; i < POT_PATTERNS.length; i++) {
final String key = POT_PATTERNS[i];
final CompoundTag tag = new CompoundTag();
tag.putString("asset_id", key + "_pottery_pattern");
entries[i] = new RegistryEntry(key, tag);
}
return entries;
}
public int[] brewingInputIds() {
return brewingInputIds;
}
@@ -18,6 +18,7 @@
package com.viaversion.viaversion.protocols.v26_2to26_3.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -36,6 +37,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrim26_3;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrimMaterial1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrimMaterial26_3;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
@@ -201,6 +203,10 @@ public final class BlockItemPacketRewriter26_3 extends StructuredItemRewriter<Cl
@Override
protected void handleItemDataComponentsToClient(final UserConnection connection, final Item item, final StructuredDataContainer container) {
upgradeData(container);
// Add data components to fix issues in older protocols
appendItemDataFixComponents(connection, item, container);
super.handleItemDataComponentsToClient(connection, item, container);
}
@@ -210,10 +216,31 @@ public final class BlockItemPacketRewriter26_3 extends StructuredItemRewriter<Cl
super.handleItemDataComponentsToServer(connection, item, container);
}
private void appendItemDataFixComponents(final UserConnection connection, final Item item, final StructuredDataContainer container) {
final ProtocolVersion serverVersion = connection.getProtocolInfo().serverProtocolVersion();
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_12_2)) {
// Axes only started stripping logs in 1.13
if (item.identifier() == 1043 || item.identifier() == 1033 || item.identifier() == 1053 || item.identifier() == 1058 || item.identifier() == 1048 || item.identifier() == 1038 || item.identifier() == 1028) {
container.setEmpty(StructuredDataKey.BLOCK_TRANSFORMER);
}
}
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_8)) {
// Shovels only started creating dirt paths in 1.9
if (item.identifier() == 1036 || item.identifier() == 1046 || item.identifier() == 1041 || item.identifier() == 1026 || item.identifier() == 1056 || item.identifier() == 1031 || item.identifier() == 1051) {
container.setEmpty(StructuredDataKey.BLOCK_TRANSFORMER);
}
}
}
public static void upgradeData(final StructuredDataContainer container) {
container.remove(StructuredDataKey.MAP_COLOR);
container.replaceKey(StructuredDataKey.INSTRUMENT26_1, StructuredDataKey.INSTRUMENT26_3);
if (container.hasEmpty(StructuredDataKey.SWING_ANIMATION)) {
container.remove(StructuredDataKey.SWING_ANIMATION);
container.setEmpty(StructuredDataKey.ATTACK_ANIMATION);
container.setEmpty(StructuredDataKey.INTERACT_ANIMATION);
}
container.replace(StructuredDataKey.SWING_ANIMATION, animation -> {
container.set(StructuredDataKey.ATTACK_ANIMATION, animation);
container.set(StructuredDataKey.INTERACT_ANIMATION, animation);
@@ -352,6 +379,11 @@ public final class BlockItemPacketRewriter26_3 extends StructuredItemRewriter<Cl
}
backupTrimMaterial(backupTag, "provides_trim_material", container.get(StructuredDataKey.PROVIDES_TRIM_MATERIAL26_1));
final Integer mapColor = container.get(StructuredDataKey.MAP_COLOR);
if (mapColor != null) {
backupTag.putInt("map_color", mapColor);
}
}
private void backupTrimMaterial(final CompoundTag tag, final String key, @Nullable final Holder<ArmorTrimMaterial1_20_5> materialHolder) {
@@ -386,6 +418,11 @@ public final class BlockItemPacketRewriter26_3 extends StructuredItemRewriter<Cl
if (providesTrimMaterialTag != null) {
container.replace(StructuredDataKey.PROVIDES_TRIM_MATERIAL26_3, StructuredDataKey.PROVIDES_TRIM_MATERIAL26_1, material -> restoreTrimMaterial(material, providesTrimMaterialTag));
}
final IntTag mapColorTag = backupTag.getIntTag("map_color");
if (mapColorTag != null) {
container.set(StructuredDataKey.MAP_COLOR, mapColorTag.asInt());
}
}
private Holder<ArmorTrimMaterial1_20_5> restoreTrimMaterial(final Holder<ArmorTrimMaterial26_3> holder, final CompoundTag tag) {
@@ -18,12 +18,15 @@
package com.viaversion.viaversion.protocols.v26_2to26_3.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.protocols.v26_2to26_3.Protocol26_2To26_3;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.util.Key;
import java.util.function.UnaryOperator;
public final class RegistryDataRewriter26_3 extends RegistryDataRewriter {
@@ -36,9 +39,10 @@ public final class RegistryDataRewriter26_3 extends RegistryDataRewriter {
final StringTag condition = term.removeUnchecked("condition");
if (condition != null) {
term.put("type", condition);
updateNumberProviders(term, condition);
}
if (Key.equals(condition.getValue(), "damage_source_properties")) {
if (condition != null && Key.equals(condition.getValue(), "damage_source_properties")) {
final CompoundTag predicate = term.getCompoundTag("predicate");
if (predicate != null) {
final ListTag<CompoundTag> tags = predicate.getListTag("tags", CompoundTag.class);
@@ -51,7 +55,7 @@ public final class RegistryDataRewriter26_3 extends RegistryDataRewriter {
super.updateEnchantmentTerm(term);
// has to run after super, which maps the block id under the old key
if (Key.equals(condition.getValue(), "block_state_property")) {
if (condition != null && Key.equals(condition.getValue(), "block_state_property")) {
condition.setValue("minecraft:match_block");
term.put("blocks", term.remove("block"));
@@ -62,6 +66,117 @@ public final class RegistryDataRewriter26_3 extends RegistryDataRewriter {
}
}
// Number providers have been split into int and float providers
private static void updateNumberProviders(final CompoundTag term, final StringTag condition) {
if (Key.equals(condition.getValue(), "value_check")) {
condition.setValue("int_value_check");
convert(term, "value", "value", RegistryDataRewriter26_3::toIntProvider);
convert(term, "range", "test", RegistryDataRewriter26_3::updateIntRange);
} else if (Key.equals(condition.getValue(), "time_check")) {
convert(term, "value", "value", RegistryDataRewriter26_3::updateIntRange);
} else if (Key.equals(condition.getValue(), "random_chance")) {
convert(term, "chance", "chance", RegistryDataRewriter26_3::toFloatProvider);
}
}
private static Tag updateIntRange(final Tag range) {
if (range instanceof CompoundTag rangeTag) {
convert(rangeTag, "min", "min", RegistryDataRewriter26_3::toIntProvider);
convert(rangeTag, "max", "max", RegistryDataRewriter26_3::toIntProvider);
}
return range;
}
// Old providers were floats, with getInt rounding the value
private static Tag toIntProvider(final Tag tag) {
if (tag instanceof NumberTag numberTag) {
return new IntTag(Math.round(numberTag.asFloat()));
} else if (tag instanceof CompoundTag provider) {
final String type = provider.getString("type");
if (Key.equals(type, "binomial")) {
convert(provider, "n", "n", RegistryDataRewriter26_3::toIntProvider);
convert(provider, "p", "p", RegistryDataRewriter26_3::toFloatProvider);
return provider;
} else if (Key.equals(type, "score") && provider.getFloat("scale", 1) == 1) {
provider.remove("scale");
return provider;
}
}
return unary("from_float", unary("round", toFloatProvider(tag)));
}
private static Tag toFloatProvider(final Tag tag) {
if (!(tag instanceof CompoundTag provider)) {
return tag;
}
// Untyped providers used to fall back to uniform
switch (Key.stripMinecraftNamespace(provider.getString("type", "uniform"))) {
case "uniform" -> {
provider.putString("type", "minecraft:uniform");
convert(provider, "min", "min", RegistryDataRewriter26_3::toFloatProvider);
convert(provider, "max", "max", RegistryDataRewriter26_3::toFloatProvider);
}
case "sum" -> {
provider.putString("type", "minecraft:add");
convert(provider, "summands", "inputs", summands -> {
final ListTag<CompoundTag> inputs = new ListTag<>(CompoundTag.class);
if (summands instanceof ListTag<?> summandsList) {
for (final Tag summand : summandsList) {
inputs.add(toFloatProviderCompound(summand));
}
}
return inputs;
});
}
case "binomial" -> {
return unary("from_int", toIntProvider(provider));
}
case "score" -> {
final Tag scale = provider.remove("scale");
final CompoundTag score = unary("from_int", provider);
if (scale == null) {
return score;
}
final ListTag<CompoundTag> inputs = new ListTag<>(CompoundTag.class);
inputs.add(score);
inputs.add(toFloatProviderCompound(scale));
final CompoundTag product = new CompoundTag();
product.putString("type", "minecraft:mul");
product.put("inputs", inputs);
return product;
}
}
return provider;
}
private static CompoundTag toFloatProviderCompound(final Tag tag) {
final Tag provider = toFloatProvider(tag);
if (provider instanceof CompoundTag compoundTag) {
return compoundTag;
}
final CompoundTag constant = new CompoundTag();
constant.putString("type", "minecraft:constant");
constant.put("value", provider);
return constant;
}
private static CompoundTag unary(final String type, final Tag input) {
final CompoundTag provider = new CompoundTag();
provider.putString("type", "minecraft:" + type);
provider.put("input", input);
return provider;
}
private static void convert(final CompoundTag tag, final String key, final String newKey, final UnaryOperator<Tag> converter) {
final Tag value = tag.remove(key);
if (value != null) {
tag.put(newKey, converter.apply(value));
}
}
@Override
public boolean updateBlockStateProvider(final CompoundTag tag) {
final StringTag typeTag = tag.getStringTag("type");
@@ -86,8 +86,10 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
switch (key) {
case "enchantment" -> updateEnchantments(connection, entries);
case "trim_material" -> updateTrimMaterials(entries);
case "jukebox_song" -> updateJukeboxSongs(entries);
case "trim_material" -> updateTrimMaterials(connection, entries);
case "jukebox_song" -> updateJukeboxSongs(connection, entries);
case "trim_pattern", "instrument" -> updateTextComponents(connection, entries, "description");
case "painting_variant" -> updateTextComponents(connection, entries, "title", "author");
case "worldgen/biome" -> updateBiomes(entries);
case "worldgen/block_state_provider" -> updateBlockStateProviders(entries);
case "dimension_type" -> updateDimensionTypes(entries);
@@ -291,6 +293,18 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
updateTextComponent(connection, tag, "tooltip");
}
protected void updateTextComponents(final UserConnection connection, final RegistryEntry[] entries, final String... keys) {
for (final RegistryEntry entry : entries) {
if (!(entry.tag() instanceof final CompoundTag tag)) {
continue;
}
for (final String key : keys) {
updateTextComponent(connection, tag, key);
}
}
}
protected void updateTextComponent(final UserConnection connection, @Nullable final CompoundTag tag, final String key) {
if (tag != null && protocol.getComponentRewriter() != null) {
protocol.getComponentRewriter().processTag(connection, tag.get(key));
@@ -333,6 +347,7 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
}
final CompoundTag tag = (CompoundTag) entry.tag();
updateTextComponent(connection, tag, "description");
if (!Mappings.isFullIdentity(protocol.getMappingData().getFullItemMappings())) {
updateItemList(tag.getListTag("supported_items", StringTag.class));
updateItemList(tag.getListTag("primary_items", StringTag.class));
@@ -365,7 +380,8 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
}
}
public void updateTrimMaterials(final RegistryEntry[] entries) {
public void updateTrimMaterials(final UserConnection connection, final RegistryEntry[] entries) {
updateTextComponents(connection, entries, "description");
if (Mappings.isFullIdentity(protocol.getMappingData().getFullItemMappings())) {
return;
}
@@ -384,7 +400,8 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
}
}
public void updateJukeboxSongs(final RegistryEntry[] entries) {
public void updateJukeboxSongs(final UserConnection connection, final RegistryEntry[] entries) {
updateTextComponents(connection, entries, "description");
// can be overridden
}
@@ -454,6 +471,14 @@ public class RegistryDataRewriter implements com.viaversion.viaversion.api.rewri
}
}
}
Tag dripstoneParticle = TagUtil.getNamespacedTag(tag, "visual/default_dripstone_particle");
if (dripstoneParticle instanceof CompoundTag modifierTag && modifierTag.contains("argument")) {
dripstoneParticle = modifierTag.get("argument");
}
if (dripstoneParticle instanceof CompoundTag particle) {
handleParticleData(particle);
}
}
private void updateNestedEffect(final CompoundTag effectsTag) {
+2 -2
View File
@@ -1,10 +1,10 @@
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
projectVersion=5.12.1-SNAPSHOT
projectVersion=5.12.1
# Smile emoji (note that modrinth may not have added the version on release yet)
mcVersions=26.3, 26.2, 26.1.2, 26.1.1, 26.1, 1.21.11, 1.21.10, 1.21.9, 1.21.8, 1.21.7, 1.21.6, 1.21.5, 1.21.4, 1.21.3, 1.21.2, 1.21.1, 1.21, 1.20.6, 1.20.5, 1.20.4, 1.20.3, 1.20.2, 1.20.1, 1.20, 1.19.4, 1.19.3, 1.19.2, 1.19.1, 1.19, 1.18.2, 1.18.1, 1.18, 1.17.1, 1.17, 1.16.5, 1.16.4, 1.16.3, 1.16.2, 1.16.1, 1.16, 1.15.2, 1.15.1, 1.15, 1.14.4, 1.14.3, 1.14.2, 1.14.1, 1.14, 1.13.2, 1.13.1, 1.13, 1.12.2, 1.12.1, 1.12, 1.11.2, 1.11.1, 1.11, 1.10.2, 1.10.1, 1.10, 1.9.4, 1.9.3, 1.9.2, 1.9.1, 1.9, 1.8.9
mcVersionRange=1.8-26.3
velocityVersion=3.4-4.2.0
velocityVersion=3.4-4.2.1
# Gradle properties
org.gradle.daemon=true
+2 -2
View File
@@ -5,7 +5,7 @@ metadata.format.version = "1.1"
gson = "2.14.0"
snakeYaml = "2.6"
fastutil = "8.5.15"
vianbt = "5.3.0"
vianbt = "5.4.0"
mcstructs = "5-3.3.2-SNAPSHOT"
# Common provided
@@ -14,7 +14,7 @@ guava = "17.0"
junit = "6.1.3"
platformLauncher = "6.1.3"
checkerQual = "4.2.2"
checkerQual = "4.3.0"
# Platforms
paper = "1.20.4-R0.1-SNAPSHOT"
Binary file not shown.
+2 -2
View File
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
distributionSha256Sum=dce76f55f8e251a3a1f130eb120f30b3d271de2b76c9b0729d316b5a1b6dc01f
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.1-bin.zip
networkTimeout=10000
retries=0
retryBackOffMs=500
Vendored
+41 -11
View File
@@ -26,6 +26,33 @@
@rem Set local scope for the variables, and ensure extensions are enabled
setlocal EnableExtensions
@rem Catch executions from older scripts and ensure they exit cleanly.
@rem This can be removed once we can be reasonably confident that few people
@rem will be migrating directly to this new wrapper.
goto afterSafetyNet
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
goto exitWithErrorLevel
:afterSafetyNet
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
@@ -45,13 +72,14 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
1>&2 echo.
1>&2 echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
1>&2 echo.
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
1>&2 echo location of your Java installation.
"%COMSPEC%" /c exit 1
goto exitWithErrorLevel
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
@@ -59,13 +87,14 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
1>&2 echo.
1>&2 echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
1>&2 echo.
1>&2 echo Please set the JAVA_HOME variable in your environment to match the
1>&2 echo location of your Java installation.
"%COMSPEC%" /c exit 1
goto exitWithErrorLevel
:execute
@rem Setup the command line
@@ -75,8 +104,9 @@ echo location of your Java installation. 1>&2
@rem Execute gradlew
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
@rem which allows us to clear the local environment before executing the java command
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel & goto exitWithErrorLevel
@rem This label must not be changed. We rely on old scripts being able to jump to this point.
:exitWithErrorLevel
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
"%COMSPEC%" /c exit %ERRORLEVEL%
+20 -4
View File
@@ -1,3 +1,5 @@
import com.modrinth.minotaur.TaskModrinthUpload
plugins {
id("io.papermc.hangar-publish-plugin") version "0.1.4"
id("com.modrinth.minotaur") version "2.+"
@@ -44,10 +46,10 @@ if (runNumber != null && (!isRelease || isMainBranch)) { // Only publish release
"[$commitHash](https://github.com/ViaVersion/ViaVersion/commit/$commitHash) ${rootProject.latestCommitMessage()}"
}
val mcVersions: List<String> = (property("mcVersions") as String)
.split(",")
.map { it.trim() }
modrinth {
val mcVersions: List<String> = (property("mcVersions") as String)
.split(",")
.map { it.trim() }
token.set(System.getenv("MODRINTH_TOKEN"))
projectId.set("viaversion")
versionType.set(if (isRelease) "release" else if (isMainBranch) "beta" else "alpha")
@@ -56,7 +58,6 @@ if (runNumber != null && (!isRelease || isMainBranch)) { // Only publish release
changelog.set(changelogContent)
uploadFile.set(tasks.shadowJar.flatMap { it.archiveFile })
gameVersions.set(mcVersions)
loaders.add("fabric")
loaders.add("paper")
loaders.add("folia")
loaders.add("velocity")
@@ -70,6 +71,21 @@ if (runNumber != null && (!isRelease || isMainBranch)) { // Only publish release
}
tasks.modrinth {
notCompatibleWithConfigurationCache("")
finalizedBy("modrinthFabric")
}
// Fabric requires 1.14+ (18w43b), so it is uploaded separately with only the supported versions
val modrinthExtension = modrinth
tasks.register<TaskModrinthUpload>("modrinthFabric") {
group = "publishing"
dependsOn(tasks.assemble)
notCompatibleWithConfigurationCache("")
doFirst {
modrinthExtension.loaders.set(listOf("fabric"))
modrinthExtension.gameVersions.set(mcVersions.filter { version ->
val (major, minor) = version.split(".").map(String::toInt)
major > 1 || minor >= 14
})
}
}
hangarPublish {