Compare commits

..
Author SHA1 Message Date
Nassim Jahnke 0a55311e1c 5.0.0 Release 2024-06-16 15:46:27 +02:00
Nassim Jahnke d1d279cfea Don't send the attribute packet if the login packet hasn't been sent yet 2024-06-16 15:44:02 +02:00
Nassim Jahnke 4b44ecf6fa Fix missed null item return value 2024-06-16 15:00:23 +02:00
Nassim Jahnke b9474335e8 Fix container item type 2024-06-16 10:48:53 +02:00
Nassim Jahnke f0c26d5967 Make sure we actually have block mappings before trying to apply them 2024-06-16 10:19:50 +02:00
Nassim Jahnke aa312f7332 Merge branch 'refs/heads/dev' into preview 2024-06-16 10:19:43 +02:00
Nassim Jahnke 4210463505 Don't return null item in compound tag reading 2024-06-15 22:56:19 +02:00
EnZaXD ec976dfb6c Add method to remove sub commands from command handler (#3941) 2024-06-15 20:51:24 +02:00
Nassim Jahnke 7e60300e2e Merge branch 'refs/heads/dev' into preview 2024-06-15 16:11:04 +02:00
EnZaXD 9a9ca9676d Cleanup /viaversion list and pps command (#3933) 2024-06-15 15:53:09 +02:00
EnZaXD c68915b261 Add /viaversion player <name|*> command (#3932) 2024-06-15 15:05:26 +02:00
Nassim Jahnke 524e053327 Don't add tags if they're already in there 2024-06-14 17:04:22 +02:00
EnZaXD 9e523c353a Fix book signing in 1.8->1.9 (#3939) 2024-06-14 10:17:42 +02:00
Nassim Jahnke 00088a90fd Keep data component types fully immutable 2024-06-14 00:27:56 +02:00
Nassim Jahnke ddf6df8097 Add new keys for item data types containing item arrays 2024-06-14 00:21:30 +02:00
Nassim Jahnke 794683ef75 Don't use ItemStack.empty()
This is a fairly new method
2024-06-13 23:22:18 +02:00
Nassim Jahnke cc6f789334 Handle block ids in tool and adventure more predicate data 2024-06-13 23:10:25 +02:00
EnZaXD 4a70e0ea2a Fixup command registration once again (#3937) 2024-06-13 19:21:52 +02:00
EnZaXD 72cc9e9968 Add ability to detection level in /viaversion displayleaks (#3934) 2024-06-13 18:36:08 +02:00
EnZaXD 1039b8556b Add remaining item types to item rewriter implementations (#3931) 2024-06-13 18:34:55 +02:00
Nassim Jahnke e977e8db90 Write sound in explosion as proper sound event in 1.20.3->1.20.5 2024-06-13 18:30:28 +02:00
Nassim Jahnke 877053c471 Send mining efficiency attribute on item switch
For some reason, mining efficiency is not calculated by the client anymore, but by the server, then sending the current value to the client every time the item changes. This roughly emulates that behavior (without tracking any inventory state beyond events).
2024-06-13 18:21:55 +02:00
Nassim Jahnke 67a349d74b Add tooltip_order and manually add curse enchantment tags 2024-06-12 23:22:46 +02:00
RK_01 009e2deed1 Add important 1.21 tags (#4) 2024-06-12 20:36:15 +02:00
Nassim Jahnke bb59149fbd Remove snapshot version for 1.21 2024-06-12 18:10:45 +02:00
Nassim Jahnke 089df6517e 1.21-rc1 2024-06-12 18:03:51 +02:00
Nassim Jahnke d007beaeec 1.21-pre4 2024-06-12 18:03:51 +02:00
Nassim Jahnke 3d656d411d 1.21-pre3 2024-06-12 18:03:51 +02:00
Nassim Jahnke 2c44c275bc 1.21-pre2 2024-06-12 18:03:51 +02:00
Nassim Jahnke d062229e0f Fix item type in 1.21 entity data types 2024-06-12 18:03:51 +02:00
Nassim Jahnke 8bc22a1bad Handle item changes in show item components 2024-06-12 18:03:50 +02:00
Nassim Jahnke 5d0846abe2 Handle chat and horse container changes 2024-06-12 18:03:50 +02:00
Nassim Jahnke 23dd8c55ad 1.21-pre1 2024-06-12 18:03:50 +02:00
Nassim Jahnke 5edb6ff411 Handle jukebox songs 2024-06-12 18:03:50 +02:00
Nassim Jahnke 251ab42c14 Update data component ids 2024-06-12 18:03:50 +02:00
Nassim Jahnke 134c3559bf WIP 24w21b 2024-06-12 18:03:49 +02:00
Nassim Jahnke 832dbdf493 24w20a 2024-06-12 18:03:49 +02:00
Nassim Jahnke ccc509432b Rebase onto 5.0.0 2024-06-12 18:03:49 +02:00
Nassim Jahnke cf2168aa95 24w19b, they couldn't have done that 10 seconds faster 2024-06-12 18:03:49 +02:00
Nassim Jahnke 58d7dc7ca6 24w19a 2024-06-12 18:03:49 +02:00
FlorianMichael 1fe6f72aec Fix typo 2024-06-12 18:03:48 +02:00
Nassim Jahnke e3312b1c80 Add basic handling for items within item components
No changes so far, but will most likely be needed rather sooner than later
2024-06-12 18:03:48 +02:00
Nassim Jahnke 182148dbe8 Some cleanup 2024-06-12 18:03:48 +02:00
Nassim Jahnke b5c718098d 24w18a
Abstract item rewriters still need additional handling for once there are actual item changes, but this works as is for now
2024-06-12 18:03:39 +02:00
EnZaXD 01ea51e8ee Add armor stand entity id to ENTITY_DATA in 1.20.3->.5 (#3930)
Closes https://github.com/ViaVersion/ViaVersion/issues/3929
2024-06-12 18:02:24 +02:00
EnZaXD ae3042074e Add trade list rewriter functions to ItemRewriter (#3926) 2024-06-11 15:02:04 +02:00
EnZaXD d0ed528788 Save negative item amounts in 1.10->1.11 (#3921) 2024-06-09 17:07:29 +02:00
EnZaXD 2fba2c1e65 Don't send empty items in 1.8->1.9 hand item provider (#3920) 2024-06-09 15:52:08 +02:00
93 changed files with 2605 additions and 380 deletions

No files matched your search

@@ -34,6 +34,13 @@ public interface ViaVersionCommand {
*/
void registerSubCommand(ViaSubCommand command);
/**
* Removes a subcommand by name, can be used to unload default subcommands which are not supported
* on the platform.
* @param name Subcommand name
*/
void removeSubCommand(String name);
/**
* Check if a subcommand is registered.
*
@@ -52,6 +52,8 @@ public interface MappingData {
*/
int getNewBlockId(int id);
int getOldBlockId(int id);
/**
* Returns the mapped item id, or -1 if unmapped.
*
@@ -39,13 +39,13 @@ public class MappingDataBase implements MappingData {
protected final String unmappedVersion;
protected final String mappedVersion;
protected BiMappings itemMappings;
protected FullMappings argumentTypeMappings;
protected FullMappings entityMappings;
protected FullMappings recipeSerializerMappings;
protected FullMappings itemDataSerializerMappings;
protected ParticleMappings particleMappings;
protected Mappings blockMappings;
protected BiMappings itemMappings;
protected BiMappings blockMappings;
protected Mappings blockStateMappings;
protected Mappings blockEntityMappings;
protected Mappings soundMappings;
@@ -68,7 +68,7 @@ public class MappingDataBase implements MappingData {
}
final CompoundTag data = readMappingsFile("mappings-" + unmappedVersion + "to" + mappedVersion + ".nbt");
blockMappings = loadMappings(data, "blocks");
blockMappings = loadBiMappings(data, "blocks");
blockStateMappings = loadMappings(data, "blockstates");
blockEntityMappings = loadMappings(data, "blockentities");
soundMappings = loadMappings(data, "sounds");
@@ -178,6 +178,11 @@ public class MappingDataBase implements MappingData {
return checkValidity(id, blockMappings.getNewId(id), "block");
}
@Override
public int getOldBlockId(final int id) {
return blockMappings.getNewIdOrDefault(id, 1);
}
@Override
public int getNewItemId(final int id) {
return checkValidity(id, itemMappings.getNewId(id), "item");
@@ -22,6 +22,8 @@
*/
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
/**
* Set of ids that either holds a string tag key or an array of ids.
*/
@@ -76,4 +78,12 @@ public interface HolderSet {
* @return true if this holder set has direct ids, false if it has a tag key
*/
boolean hasIds();
/**
* Returns a new holder set with the ids rewritten.
*
* @param idRewriter the id rewriter
* @return a new holder set with the ids rewritten, or self if it has a tag key
*/
HolderSet rewrite(Int2IntFunction idRewriter);
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.EitherImpl;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
final class HolderSetImpl extends EitherImpl<String, int[]> implements HolderSet {
@@ -53,4 +54,18 @@ final class HolderSetImpl extends EitherImpl<String, int[]> implements HolderSet
public boolean hasIds() {
return isRight();
}
@Override
public HolderSet rewrite(final Int2IntFunction idRewriter) {
if (hasTagKey()) {
return this;
}
final int[] ids = ids();
final int[] mappedIds = new int[ids.length];
for (int i = 0; i < mappedIds.length; i++) {
mappedIds[i] = idRewriter.apply(ids[i]);
}
return new HolderSetImpl(mappedIds);
}
}
@@ -20,32 +20,28 @@
* 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;
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
public record ModifierData(UUID uuid, String name, double amount, int operation) {
public record PaintingVariant(int width, int height, String assetId) {
public static final Type<ModifierData> TYPE = new Type<>(ModifierData.class) {
public static HolderType<PaintingVariant> TYPE = new HolderType<>() {
@Override
public ModifierData read(final ByteBuf buffer) {
final UUID uuid = Types.UUID.read(buffer);
final String name = Types.STRING.read(buffer);
final double amount = buffer.readDouble();
final int operation = Types.VAR_INT.readPrimitive(buffer);
return new ModifierData(uuid, name, amount, operation);
public PaintingVariant readDirect(final ByteBuf buffer) {
final int width = Types.VAR_INT.readPrimitive(buffer);
final int height = Types.VAR_INT.readPrimitive(buffer);
final String assetId = Types.STRING.read(buffer);
return new PaintingVariant(width, height, assetId);
}
@Override
public void write(final ByteBuf buffer, final ModifierData value) {
Types.UUID.write(buffer, value.uuid);
Types.STRING.write(buffer, value.name);
buffer.writeDouble(value.amount);
Types.VAR_INT.writePrimitive(buffer, value.operation);
public void writeDirect(final ByteBuf buffer, final PaintingVariant variant) {
Types.VAR_INT.writePrimitive(buffer, variant.width());
Types.VAR_INT.writePrimitive(buffer, variant.height());
Types.STRING.write(buffer, variant.assetId());
}
};
}
@@ -32,7 +32,8 @@ public enum RegistryType {
ITEM("item"),
FLUID("fluid"),
ENTITY("entity_type"),
GAME_EVENT("game_event");
GAME_EVENT("game_event"),
ENCHANTMENT("enchantment");
private static final Map<String, RegistryType> MAP = new HashMap<>();
private static final RegistryType[] VALUES = values();
@@ -20,31 +20,30 @@
* 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;
package com.viaversion.viaversion.api.minecraft;
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.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
public record WolfVariant(String wildTexture, String tameTexture, String angryTexture, HolderSet biomes) {
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
public static HolderType<WolfVariant> TYPE = new HolderType<>() {
@Override
public AttributeModifier read(final ByteBuf buffer) {
final int attribute = Types.VAR_INT.readPrimitive(buffer);
final ModifierData modifier = ModifierData.TYPE.read(buffer);
final int slot = Types.VAR_INT.readPrimitive(buffer);
return new AttributeModifier(attribute, modifier, slot);
public WolfVariant readDirect(final ByteBuf buffer) {
final String wildTexture = Types.STRING.read(buffer);
final String tameTexture = Types.STRING.read(buffer);
final String angryTexture = Types.STRING.read(buffer);
final HolderSet biomes = Types.HOLDER_SET.read(buffer);
return new WolfVariant(wildTexture, tameTexture, angryTexture, biomes);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifier value) {
Types.VAR_INT.writePrimitive(buffer, value.attribute);
ModifierData.TYPE.write(buffer, value.modifier);
Types.VAR_INT.writePrimitive(buffer, value.slotType);
public void writeDirect(final ByteBuf buffer, final WolfVariant variant) {
Types.STRING.write(buffer, variant.wildTexture());
Types.STRING.write(buffer, variant.tameTexture());
Types.STRING.write(buffer, variant.angryTexture());
Types.HOLDER_SET.write(buffer, variant.biomes());
}
};
public static final Type<AttributeModifier[]> ARRAY_TYPE = new ArrayType<>(TYPE);
}
@@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.Unit;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import java.util.Map;
import java.util.function.Function;
@@ -98,6 +99,24 @@ public final class StructuredDataContainer {
return empty;
}
/**
* Updates and returns the structured data by id if not empty.
*
* @param key serializer id
* @param mappingFunction function to update existing data
* @param <T> data type
* @return updated structured data if not empty
*/
public <T> @Nullable StructuredData<T> updateIfPresent(final StructuredDataKey<T> key, final Function<T, T> mappingFunction) {
final StructuredData<T> data = this.getNonEmpty(key);
if (data == null) {
return null;
}
data.setValue(mappingFunction.apply(data.value()));
return data;
}
public <T> void set(final StructuredDataKey<T> key, final T value) {
final int id = serializerId(key);
if (id != -1) {
@@ -105,6 +124,23 @@ public final class StructuredDataContainer {
}
}
public <T> void replaceKey(final StructuredDataKey<T> key, final StructuredDataKey<T> toKey) {
replace(key, toKey, Function.identity());
}
public <T, V> void replace(final StructuredDataKey<T> key, final StructuredDataKey<V> toKey, final Function<T, V> valueMapper) {
final StructuredData<T> data = remove(key);
if (data == null) {
return;
}
if (data.isPresent()) {
set(toKey, valueMapper.apply(data.value()));
} else {
addEmpty(toKey);
}
}
public void set(final StructuredDataKey<Unit> key) {
this.set(key, Unit.INSTANCE);
}
@@ -143,6 +179,17 @@ public final class StructuredDataContainer {
this.mappedNames = mappedNames;
}
public void updateIds(final Protocol<?, ?, ?, ?> protocol, final Int2IntFunction rewriter) {
for (final StructuredData<?> data : data.values()) {
final int mappedId = rewriter.applyAsInt(data.id());
if (mappedId == -1) {
continue;
}
data.setId(mappedId);
}
}
public StructuredDataContainer copy() {
final StructuredDataContainer copy = new StructuredDataContainer(new Reference2ObjectOpenHashMap<>(data));
copy.lookup = this.lookup;
@@ -29,7 +29,8 @@ import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.item.Item;
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.AttributeModifiers;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
@@ -40,6 +41,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.FireworkExplosion;
import com.viaversion.viaversion.api.minecraft.item.data.Fireworks;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument;
import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
@@ -50,6 +52,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.util.Unit;
public record StructuredDataKey<T>(String identifier, Type<T> type) {
@@ -66,7 +69,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Enchantments> ENCHANTMENTS = new StructuredDataKey<>("enchantments", Enchantments.TYPE);
public static final StructuredDataKey<AdventureModePredicate> CAN_PLACE_ON = new StructuredDataKey<>("can_place_on", AdventureModePredicate.TYPE);
public static final StructuredDataKey<AdventureModePredicate> CAN_BREAK = new StructuredDataKey<>("can_break", AdventureModePredicate.TYPE);
public static final StructuredDataKey<AttributeModifiers> ATTRIBUTE_MODIFIERS = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers.TYPE);
public static final StructuredDataKey<AttributeModifiers1_20_5> ATTRIBUTE_MODIFIERS1_20_5 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_20_5.TYPE);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE);
public static final StructuredDataKey<Integer> CUSTOM_MODEL_DATA = new StructuredDataKey<>("custom_model_data", Types.VAR_INT);
public static final StructuredDataKey<Unit> HIDE_ADDITIONAL_TOOLTIP = new StructuredDataKey<>("hide_additional_tooltip", Types.EMPTY);
public static final StructuredDataKey<Unit> HIDE_TOOLTIP = new StructuredDataKey<>("hide_tooltip", Types.EMPTY);
@@ -74,7 +78,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Unit> CREATIVE_SLOT_LOCK = new StructuredDataKey<>("creative_slot_lock", Types.EMPTY);
public static final StructuredDataKey<Boolean> ENCHANTMENT_GLINT_OVERRIDE = new StructuredDataKey<>("enchantment_glint_override", Types.BOOLEAN);
public static final StructuredDataKey<Tag> INTANGIBLE_PROJECTILE = new StructuredDataKey<>("intangible_projectile", Types.TAG); // Doesn't actually hold data
public static final StructuredDataKey<FoodProperties> FOOD = new StructuredDataKey<>("food", FoodProperties.TYPE);
public static final StructuredDataKey<FoodProperties> FOOD1_20_5 = new StructuredDataKey<>("food", FoodProperties.TYPE1_20_5);
public static final StructuredDataKey<FoodProperties> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties.TYPE1_21);
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
public static final StructuredDataKey<ToolProperties> TOOL = new StructuredDataKey<>("tool", ToolProperties.TYPE);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE);
@@ -83,8 +88,10 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> MAP_ID = new StructuredDataKey<>("map_id", Types.VAR_INT);
public static final StructuredDataKey<CompoundTag> MAP_DECORATIONS = new StructuredDataKey<>("map_decorations", Types.COMPOUND_TAG);
public static final StructuredDataKey<Integer> MAP_POST_PROCESSING = new StructuredDataKey<>("map_post_processing", Types.VAR_INT);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES = new StructuredDataKey<>("charged_projectiles", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS = new StructuredDataKey<>("bundle_contents", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_20_5 = new StructuredDataKey<>("charged_projectiles", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21 = new StructuredDataKey<>("charged_projectiles", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_20_5 = new StructuredDataKey<>("bundle_contents", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21 = new StructuredDataKey<>("bundle_contents", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<PotionContents> POTION_CONTENTS = new StructuredDataKey<>("potion_contents", PotionContents.TYPE);
public static final StructuredDataKey<SuspiciousStewEffect[]> SUSPICIOUS_STEW_EFFECTS = new StructuredDataKey<>("suspicious_stew_effects", SuspiciousStewEffect.ARRAY_TYPE);
public static final StructuredDataKey<FilterableString[]> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", FilterableString.ARRAY_TYPE);
@@ -96,6 +103,7 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<CompoundTag> BLOCK_ENTITY_DATA = new StructuredDataKey<>("block_entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<Holder<Instrument>> INSTRUMENT = new StructuredDataKey<>("instrument", Instrument.TYPE);
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.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);
@@ -105,7 +113,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<BannerPatternLayer[]> BANNER_PATTERNS = new StructuredDataKey<>("banner_patterns", BannerPatternLayer.ARRAY_TYPE);
public static final StructuredDataKey<Integer> BASE_COLOR = new StructuredDataKey<>("base_color", Types.VAR_INT);
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
public static final StructuredDataKey<Item[]> CONTAINER = new StructuredDataKey<>("container", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_20_5 = new StructuredDataKey<>("container", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_21 = new StructuredDataKey<>("container", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<BlockStateProperties> BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE);
public static final StructuredDataKey<Bee[]> BEES = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE);
public static final StructuredDataKey<Tag> LOCK = new StructuredDataKey<>("lock", Types.TAG);
@@ -0,0 +1,73 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.Particle;
import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
public final class EntityDataTypes1_21 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.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType itemType = add(7, Types1_21.ITEM);
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 compoundTagType = add(16, Types.COMPOUND_TAG);
public final EntityDataType particleType;
public final EntityDataType particlesType;
public final EntityDataType villagerDatatType = add(19, Types.VILLAGER_DATA);
public final EntityDataType optionalVarIntType = add(20, Types.OPTIONAL_VAR_INT);
public final EntityDataType poseType = add(21, Types.VAR_INT);
public final EntityDataType catVariantType = add(22, Types.VAR_INT);
public final EntityDataType wolfVariantType = add(23, WolfVariant.TYPE);
public final EntityDataType frogVariantType = add(24, Types.VAR_INT);
public final EntityDataType optionalGlobalPosition = add(25, Types.OPTIONAL_GLOBAL_POSITION);
public final EntityDataType paintingVariantType = add(26, PaintingVariant.TYPE);
public final EntityDataType snifferState = add(27, Types.VAR_INT);
public final EntityDataType armadilloState = add(28, Types.VAR_INT);
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
public EntityDataTypes1_21(final ParticleType particleType, final ArrayType<Particle> particlesType) {
super(31);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
}
}
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record AdventureModePredicate(BlockPredicate[] predicates, boolean showInTooltip) {
@@ -42,4 +43,11 @@ public record AdventureModePredicate(BlockPredicate[] predicates, boolean showIn
}
};
public AdventureModePredicate rewrite(final Int2IntFunction blockIdRewriter) {
final BlockPredicate[] predicates = new BlockPredicate[this.predicates.length];
for (int i = 0; i < predicates.length; i++) {
predicates[i] = this.predicates[i].rewrite(blockIdRewriter);
}
return new AdventureModePredicate(predicates, showInTooltip);
}
}
@@ -25,6 +25,7 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern, boolean showInTooltip) {
@@ -45,4 +46,16 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
}
};
public ArmorTrim rewrite(final Int2IntFunction idRewriteFunction) {
Holder<ArmorTrimMaterial> material = this.material;
if (material.isDirect()) {
material = Holder.of(material.value().rewrite(idRewriteFunction));
}
Holder<ArmorTrimPattern> pattern = this.pattern;
if (pattern.isDirect()) {
pattern = Holder.of(pattern.value().rewrite(idRewriteFunction));
}
return new ArmorTrim(material, pattern, showInTooltip);
}
}
@@ -26,6 +26,7 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -67,4 +68,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
};
public ArmorTrimMaterial rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimMaterial(assetName, idRewriteFunction.applyAsInt(itemId), itemModelIndex, overrideArmorMaterials, description);
}
}
@@ -26,6 +26,7 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrimPattern(String assetName, int itemId, Tag description, boolean decal) {
@@ -48,4 +49,7 @@ public record ArmorTrimPattern(String assetName, int itemId, Tag description, bo
}
};
public ArmorTrimPattern rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimPattern(assetName, idRewriteFunction.applyAsInt(itemId), description, decal);
}
}
@@ -0,0 +1,90 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean showInTooltip) {
public static final Type<AttributeModifiers1_20_5> TYPE = new Type<>(AttributeModifiers1_20_5.class) {
@Override
public AttributeModifiers1_20_5 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new AttributeModifiers1_20_5(modifiers, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_20_5 value) {
AttributeModifier.ARRAY_TYPE.write(buffer, value.modifiers());
buffer.writeBoolean(value.showInTooltip());
}
};
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
@Override
public AttributeModifier read(final ByteBuf buffer) {
final int attribute = Types.VAR_INT.readPrimitive(buffer);
final ModifierData modifier = ModifierData.TYPE.read(buffer);
final int slot = Types.VAR_INT.readPrimitive(buffer);
return new AttributeModifier(attribute, modifier, slot);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifier value) {
Types.VAR_INT.writePrimitive(buffer, value.attribute);
ModifierData.TYPE.write(buffer, value.modifier);
Types.VAR_INT.writePrimitive(buffer, value.slotType);
}
};
public static final Type<AttributeModifier[]> ARRAY_TYPE = new ArrayType<>(TYPE);
}
public record ModifierData(UUID uuid, String name, double amount, int operation) {
public static final Type<ModifierData> TYPE = new Type<>(ModifierData.class) {
@Override
public ModifierData read(final ByteBuf buffer) {
final UUID uuid = Types.UUID.read(buffer);
final String name = Types.STRING.read(buffer);
final double amount = buffer.readDouble();
final int operation = Types.VAR_INT.readPrimitive(buffer);
return new ModifierData(uuid, name, amount, operation);
}
@Override
public void write(final ByteBuf buffer, final ModifierData value) {
Types.UUID.write(buffer, value.uuid);
Types.STRING.write(buffer, value.name);
buffer.writeDouble(value.amount);
Types.VAR_INT.writePrimitive(buffer, value.operation);
}
};
}
}
@@ -0,0 +1,87 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) {
public static final Type<AttributeModifiers1_21> TYPE = new Type<>(AttributeModifiers1_21.class) {
@Override
public AttributeModifiers1_21 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new AttributeModifiers1_21(modifiers, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_21 value) {
AttributeModifier.ARRAY_TYPE.write(buffer, value.modifiers());
buffer.writeBoolean(value.showInTooltip());
}
};
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
@Override
public AttributeModifier read(final ByteBuf buffer) {
final int attribute = Types.VAR_INT.readPrimitive(buffer);
final ModifierData modifier = ModifierData.TYPE.read(buffer);
final int slot = Types.VAR_INT.readPrimitive(buffer);
return new AttributeModifier(attribute, modifier, slot);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifier value) {
Types.VAR_INT.writePrimitive(buffer, value.attribute);
ModifierData.TYPE.write(buffer, value.modifier);
Types.VAR_INT.writePrimitive(buffer, value.slotType);
}
};
public static final Type<AttributeModifier[]> ARRAY_TYPE = new ArrayType<>(TYPE);
}
public record ModifierData(String id, double amount, int operation) {
public static final Type<ModifierData> TYPE = new Type<>(ModifierData.class) {
@Override
public ModifierData read(final ByteBuf buffer) {
final String id = Types.STRING.read(buffer);
final double amount = buffer.readDouble();
final int operation = Types.VAR_INT.readPrimitive(buffer);
return new ModifierData(id, amount, operation);
}
@Override
public void write(final ByteBuf buffer, final ModifierData value) {
Types.STRING.write(buffer, value.id);
buffer.writeDouble(value.amount);
Types.VAR_INT.writePrimitive(buffer, value.operation);
}
};
}
}
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher @Nullable [] propertyMatchers,
@@ -56,4 +57,12 @@ public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher
};
public static final Type<BlockPredicate[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public BlockPredicate rewrite(final Int2IntFunction blockIdRewriter) {
if (holderSet == null || holderSet.hasTagKey()) {
return this;
}
final HolderSet updatedHolders = holderSet.rewrite(blockIdRewriter);
return new BlockPredicate(updatedHolders, propertyMatchers, tag);
}
}
@@ -0,0 +1,68 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.Tag;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration narrationDecoration) {
public static final HolderType<ChatType> TYPE = new HolderType<>() {
@Override
public ChatType readDirect(final ByteBuf buffer) {
final ChatTypeDecoration chatDecoration = ChatTypeDecoration.TYPE.read(buffer);
final ChatTypeDecoration narrationDecoration = ChatTypeDecoration.TYPE.read(buffer);
return new ChatType(chatDecoration, narrationDecoration);
}
@Override
public void writeDirect(final ByteBuf buffer, final ChatType value) {
ChatTypeDecoration.TYPE.write(buffer, value.chatDecoration());
ChatTypeDecoration.TYPE.write(buffer, value.narrationDecoration());
}
};
public record ChatTypeDecoration(String translationKey, int[] parameters, Tag style) {
public static final Type<ChatTypeDecoration> TYPE = new Type<>(ChatTypeDecoration.class) {
@Override
public ChatTypeDecoration read(final ByteBuf buffer) {
final String translationKey = Types.STRING.read(buffer);
final int[] parameters = Types.INT_ARRAY_PRIMITIVE.read(buffer);
final Tag style = Types.TAG.read(buffer);
return new ChatTypeDecoration(translationKey, parameters, style);
}
@Override
public void write(final ByteBuf buffer, final ChatTypeDecoration value) {
Types.STRING.write(buffer, value.translationKey());
Types.INT_ARRAY_PRIMITIVE.write(buffer, value.parameters());
Types.TAG.write(buffer, value.style());
}
};
}
}
@@ -22,14 +22,16 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import io.netty.buffer.ByteBuf;
public record FoodProperties(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
FoodEffect[] possibleEffects) {
Item usingConvertsTo, FoodEffect[] possibleEffects) {
public static final Type<FoodProperties> TYPE = new Type<>(FoodProperties.class) {
public static final Type<FoodProperties> TYPE1_20_5 = new Type<>(FoodProperties.class) {
@Override
public FoodProperties read(final ByteBuf buffer) {
final int nutrition = Types.VAR_INT.readPrimitive(buffer);
@@ -37,7 +39,7 @@ public record FoodProperties(int nutrition, float saturationModifier, boolean ca
final boolean canAlwaysEat = buffer.readBoolean();
final float eatSeconds = buffer.readFloat();
final FoodEffect[] possibleEffects = FoodEffect.ARRAY_TYPE.read(buffer);
return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, possibleEffects);
return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, null, possibleEffects);
}
@Override
@@ -49,5 +51,26 @@ public record FoodProperties(int nutrition, float saturationModifier, boolean ca
FoodEffect.ARRAY_TYPE.write(buffer, value.possibleEffects);
}
};
public static final Type<FoodProperties> TYPE1_21 = new Type<FoodProperties>(FoodProperties.class) {
@Override
public FoodProperties read(final ByteBuf buffer) {
final int nutrition = Types.VAR_INT.readPrimitive(buffer);
final float saturationModifier = buffer.readFloat();
final boolean canAlwaysEat = buffer.readBoolean();
final float eatSeconds = buffer.readFloat();
final Item usingConvertsTo = Types1_21.OPTIONAL_ITEM.read(buffer);
final FoodEffect[] possibleEffects = FoodEffect.ARRAY_TYPE.read(buffer);
return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo, possibleEffects);
}
@Override
public void write(final ByteBuf buffer, final FoodProperties value) {
Types.VAR_INT.writePrimitive(buffer, value.nutrition);
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
buffer.writeFloat(value.eatSeconds);
Types1_21.OPTIONAL_ITEM.write(buffer, value.usingConvertsTo);
FoodEffect.ARRAY_TYPE.write(buffer, value.possibleEffects);
}
};
}
@@ -0,0 +1,81 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.Tag;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Either;
import io.netty.buffer.ByteBuf;
public record JukeboxPlayable(Either<Holder<JukeboxSong>, String> song, boolean showInTooltip) {
public JukeboxPlayable(final Holder<JukeboxSong> song, final boolean showInTooltip) {
this(Either.left(song), showInTooltip);
}
public JukeboxPlayable(final String resourceKey, final boolean showInTooltip) {
this(Either.right(resourceKey), showInTooltip);
}
public static final Type<JukeboxPlayable> TYPE = new Type<>(JukeboxPlayable.class) {
@Override
public JukeboxPlayable read(final ByteBuf buffer) {
final Either<Holder<JukeboxSong>, String> position = Type.readEither(buffer, JukeboxSong.TYPE, Types.STRING);
final boolean showInTooltip = buffer.readBoolean();
return new JukeboxPlayable(position, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final JukeboxPlayable value) {
Type.writeEither(buffer, value.song, JukeboxSong.TYPE, Types.STRING);
buffer.writeBoolean(value.showInTooltip);
}
};
public record JukeboxSong(Holder<SoundEvent> soundEvent, Tag description,
float lengthInSeconds, int comparatorOutput) {
public static final HolderType<JukeboxSong> TYPE = new HolderType<>() {
@Override
public JukeboxSong readDirect(final ByteBuf buffer) {
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final Tag description = Types.TAG.read(buffer);
final float lengthInSeconds = buffer.readFloat();
final int useDuration = Types.VAR_INT.readPrimitive(buffer);
return new JukeboxSong(soundEvent, description, lengthInSeconds, useDuration);
}
@Override
public void writeDirect(final ByteBuf buffer, final JukeboxSong value) {
Types.SOUND_EVENT.write(buffer, value.soundEvent);
Types.TAG.write(buffer, value.description);
buffer.writeFloat(value.lengthInSeconds);
Types.VAR_INT.writePrimitive(buffer, value.comparatorOutput);
}
};
}
}
@@ -25,6 +25,7 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public final class PotDecorations {
@@ -73,4 +74,12 @@ public final class PotDecorations {
private int item(final int index) {
return index < 0 || index >= itemIds.length ? -1 : itemIds[index];
}
public PotDecorations rewrite(final Int2IntFunction idRewriteFunction) {
final int[] newItems = new int[itemIds.length];
for (int i = 0; i < itemIds.length; i++) {
newItems[i] = idRewriteFunction.applyAsInt(itemIds[i]);
}
return new PotDecorations(newItems);
}
}
@@ -31,7 +31,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public record StatePropertyMatcher(String name, Either<String, RangedMatcher> matcher) {
// TODO Abstract Either reading
public static final Type<StatePropertyMatcher> TYPE = new Type<>(StatePropertyMatcher.class) {
@Override
public StatePropertyMatcher read(final ByteBuf buffer) {
@@ -25,6 +25,7 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int damagePerBlock) {
@@ -45,4 +46,11 @@ public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int dam
}
};
public ToolProperties rewrite(final Int2IntFunction blockIdRewriter) {
final ToolRule[] rules = new ToolRule[this.rules.length];
for (int i = 0; i < rules.length; i++) {
rules[i] = this.rules[i].rewrite(blockIdRewriter);
}
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock);
}
}
@@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record ToolRule(HolderSet blocks, @Nullable Float speed, @Nullable Boolean correctForDrops) {
@@ -49,4 +50,7 @@ public record ToolRule(HolderSet blocks, @Nullable Float speed, @Nullable Boolea
};
public static final Type<ToolRule[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public ToolRule rewrite(final Int2IntFunction blockIdRewriter) {
return blocks.hasIds() ? new ToolRule(blocks.rewrite(blockIdRewriter), speed, correctForDrops) : this;
}
}
@@ -33,6 +33,7 @@ import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.rewriter.TagRewriter;
@@ -382,6 +383,10 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
return null;
}
default @Nullable ComponentRewriter getComponentRewriter() {
return null;
}
/**
* Returns whether this protocol is a base protocol.
*
@@ -84,6 +84,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_20_2 = register(764, "1.20.2");
public static final ProtocolVersion v1_20_3 = register(765, "1.20.3-1.20.4", new SubVersionRange("1.20", 3, 4));
public static final ProtocolVersion v1_20_5 = register(766, "1.20.5-1.20.6", new SubVersionRange("1.20", 5, 6));
public static final ProtocolVersion v1_21 = register(767, "1.21");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
public static ProtocolVersion register(int version, String name) {
@@ -20,26 +20,16 @@
* 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;
package com.viaversion.viaversion.api.rewriter;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import com.google.gson.JsonElement;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import org.checkerframework.checker.nullness.qual.Nullable;
public record AttributeModifiers(AttributeModifier[] modifiers, boolean showInTooltip) {
public interface ComponentRewriter {
public static final Type<AttributeModifiers> TYPE = new Type<>(AttributeModifiers.class) {
@Override
public AttributeModifiers read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new AttributeModifiers(modifiers, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers value) {
AttributeModifier.ARRAY_TYPE.write(buffer, value.modifiers());
buffer.writeBoolean(value.showInTooltip());
}
};
void processTag(UserConnection connection, @Nullable Tag tag);
void processText(UserConnection connection, @Nullable JsonElement element);
}
@@ -22,6 +22,9 @@
*/
package com.viaversion.viaversion.api.type;
import com.viaversion.viaversion.util.Either;
import io.netty.buffer.ByteBuf;
/**
* Type for buffer reading and writing.
*
@@ -75,4 +78,22 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public String toString() {
return getTypeName();
}
public static <X, Y> Either<X, Y> readEither(final ByteBuf buf, final Type<X> leftType, final Type<Y> rightType) {
if (buf.readBoolean()) {
return Either.left(leftType.read(buf));
} else {
return Either.right(rightType.read(buf));
}
}
public static <X, Y> void writeEither(final ByteBuf buf, final Either<X, Y> value, final Type<X> leftType, final Type<Y> rightType) {
if (value.isLeft()) {
buf.writeBoolean(true);
leftType.write(buf, value.left());
} else {
buf.writeBoolean(false);
rightType.write(buf, value.right());
}
}
}
@@ -44,16 +44,13 @@ public class ItemType1_13 extends Type<Item> {
item.setIdentifier(id);
item.setAmount(buffer.readByte());
item.setTag(Types.NAMED_COMPOUND_TAG.read(buffer));
if (item.isEmpty()) {
return null;
}
return item;
}
}
@Override
public void write(ByteBuf buffer, @Nullable Item object) {
if (object == null || object.isEmpty()) {
if (object == null) {
buffer.writeShort(-1);
} else {
buffer.writeShort(object.identifier());
@@ -44,16 +44,13 @@ public class ItemType1_13_2 extends Type<Item> {
item.setIdentifier(Types.VAR_INT.readPrimitive(buffer));
item.setAmount(buffer.readByte());
item.setTag(Types.NAMED_COMPOUND_TAG.read(buffer));
if (item.isEmpty()) {
return null;
}
return item;
}
}
@Override
public void write(ByteBuf buffer, @Nullable Item object) {
if (object == null || object.isEmpty()) {
if (object == null) {
buffer.writeBoolean(false);
} else {
buffer.writeBoolean(true);
@@ -45,15 +45,12 @@ public class ItemType1_20_2 extends Type<Item> {
item.setIdentifier(Types.VAR_INT.readPrimitive(buffer));
item.setAmount(buffer.readByte());
item.setTag(Types.COMPOUND_TAG.read(buffer));
if (item.isEmpty()) {
return null;
}
return item;
}
@Override
public void write(final ByteBuf buffer, @Nullable final Item object) {
if (object == null || object.isEmpty()) {
if (object == null) {
buffer.writeBoolean(false);
} else {
buffer.writeBoolean(true);
@@ -28,6 +28,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.StructuredItem;
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;
@@ -114,4 +115,11 @@ public class ItemType1_20_5 extends Type<Item> {
}
}
}
public final class OptionalItemType extends OptionalType<Item> {
public OptionalItemType() {
super(ItemType1_20_5.this);
}
}
}
@@ -83,6 +83,7 @@ public class StructuredDataType extends Type<StructuredData<?>> {
public DataFiller add(final StructuredDataKey<?> key) {
final int id = mappings.mappedId(key.identifier());
Preconditions.checkArgument(id != -1, "No mapped id found for %s", key.identifier());
Preconditions.checkArgument(types[id] == null, "Data component serializer already exists for id %s", id);
types[id] = key;
return this;
}
@@ -71,8 +71,6 @@ public class ParticleType extends DynamicType<Particle> {
};
public static final DataReader<Particle> ITEM1_13 = itemHandler(Types.ITEM1_13);
public static final DataReader<Particle> ITEM1_13_2 = itemHandler(Types.ITEM1_13_2);
public static final DataReader<Particle> ITEM1_20_2 = itemHandler(Types.ITEM1_20_2);
public static final DataReader<Particle> ITEM1_20_5 = itemHandler(Types1_20_5.ITEM);
public static final DataReader<Particle> DUST = (buf, particle) -> {
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Red 0-1
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Green 0-1
@@ -139,5 +137,9 @@ public class ParticleType extends DynamicType<Particle> {
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Delay
};
public static final DataReader<Particle> COLOR = (buf, particle) -> particle.add(Types.INT, buf.readInt());
public static DataReader<Particle> item(Type<Item> item) {
return (buf, particle) -> particle.add(item, item.read(buf));
}
}
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.Particle;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21;
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.entitydata.EntityDataListType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.types.item.ItemCostType1_20_5;
import com.viaversion.viaversion.api.type.types.item.ItemType1_20_5;
import com.viaversion.viaversion.api.type.types.item.StructuredDataType;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import java.util.List;
// Most of these are only safe to use after protocol loading
public final class Types1_21 {
public static final StructuredDataType STRUCTURED_DATA = new StructuredDataType();
public static final Type<StructuredData<?>[]> STRUCTURED_DATA_ARRAY = new ArrayType<>(STRUCTURED_DATA);
public static final ItemType1_20_5 ITEM = new ItemType1_20_5(STRUCTURED_DATA);
public static final Type<Item> OPTIONAL_ITEM = ITEM.new OptionalItemType(); // Optional as in boolean prefixed, not via the amount
public static final Type<Item[]> ITEM_ARRAY = new ArrayType<>(ITEM);
public static final Type<Item> ITEM_COST = new ItemCostType1_20_5(STRUCTURED_DATA_ARRAY);
public static final Type<Item> OPTIONAL_ITEM_COST = new ItemCostType1_20_5.OptionalItemCostType(ITEM_COST);
public static final ParticleType PARTICLE = new ParticleType();
public static final ArrayType<Particle> PARTICLES = new ArrayType<>(PARTICLE);
public static final EntityDataTypes1_21 ENTITY_DATA_TYPES = new EntityDataTypes1_21(PARTICLE, PARTICLES);
public static final Type<EntityData> ENTITY_DATA = new EntityDataType(ENTITY_DATA_TYPES);
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
}
@@ -47,7 +47,7 @@ public final class Key {
}
public static boolean equals(final String firstIdentifier, final String secondIdentifier) {
return stripNamespace(firstIdentifier).equals(stripNamespace(secondIdentifier));
return stripMinecraftNamespace(firstIdentifier).equals(stripMinecraftNamespace(secondIdentifier));
}
public static String namespaced(final String identifier) {
@@ -0,0 +1,78 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.bukkit.listeners.v1_20_5to1_21;
import com.viaversion.viaversion.ViaVersionPlugin;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import io.papermc.paper.event.player.PlayerInventorySlotChangeEvent;
import org.bukkit.NamespacedKey;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.inventory.ItemStack;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* For some reason, mining efficiency is not calculated by the client anymore, but by the server,
* then sending the current value to the client every time the item changes. This roughly emulates that behavior.
*/
public final class PlayerChangeItemListener extends ViaBukkitListener {
private final Enchantment efficiency = Enchantment.getByKey(NamespacedKey.minecraft("efficiency"));
public PlayerChangeItemListener(final ViaVersionPlugin plugin) {
super(plugin, Protocol1_20_5To1_21.class);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerInventorySlotChangedEvent(final PlayerInventorySlotChangeEvent event) {
final Player player = event.getPlayer();
final ItemStack item = event.getNewItemStack();
if (event.getSlot() == player.getInventory().getHeldItemSlot()) {
sendAttributeUpdate(player, item);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerItemHeld(final PlayerItemHeldEvent event) {
final Player player = event.getPlayer();
final ItemStack item = player.getInventory().getItem(event.getNewSlot());
sendAttributeUpdate(player, item);
}
private void sendAttributeUpdate(final Player player, @Nullable final ItemStack item) {
final UserConnection connection = Via.getAPI().getConnection(player.getUniqueId());
if (connection == null || !isOnPipe(player)) {
return;
}
final EfficiencyAttributeStorage storage = connection.get(EfficiencyAttributeStorage.class);
if (storage == null) {
return;
}
final int efficiencyLevel = item != null ? item.getEnchantmentLevel(efficiency) : 0;
storage.setEfficiencyLevel(new EfficiencyAttributeStorage.StoredEfficiency(player.getEntityId(), efficiencyLevel), connection);
}
}
@@ -33,6 +33,7 @@ import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.BlockListener
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.DeathListener;
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.HandItemCache;
import com.viaversion.viaversion.bukkit.listeners.protocol1_9to1_8.PaperPatch;
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PlayerChangeItemListener;
import com.viaversion.viaversion.bukkit.providers.BukkitAckSequenceProvider;
import com.viaversion.viaversion.bukkit.providers.BukkitBlockConnectionProvider;
import com.viaversion.viaversion.bukkit.providers.BukkitInventoryQuickMoveProvider;
@@ -176,6 +177,9 @@ public class BukkitViaLoader implements ViaPlatformLoader {
Via.getManager().getProviders().use(AckSequenceProvider.class, new BukkitAckSequenceProvider(plugin));
new BlockBreakListener(plugin).register();
}
if (serverProtocolVersion.olderThan(ProtocolVersion.v1_21) && PaperViaInjector.hasClass("io.papermc.paper.event.player.PlayerInventorySlotChangeEvent")) {
new PlayerChangeItemListener(plugin).register();
}
}
private boolean hasGetHandMethod() {
@@ -30,6 +30,7 @@ import com.viaversion.viaversion.commands.defaultsubs.DumpSubCmd;
import com.viaversion.viaversion.commands.defaultsubs.ListSubCmd;
import com.viaversion.viaversion.commands.defaultsubs.PPSSubCmd;
import com.viaversion.viaversion.commands.defaultsubs.ReloadSubCmd;
import com.viaversion.viaversion.commands.defaultsubs.PlayerSubCmd;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -56,6 +57,11 @@ public abstract class ViaCommandHandler implements ViaVersionCommand {
commandMap.put(command.name().toLowerCase(Locale.ROOT), command);
}
@Override
public void removeSubCommand(final String name) {
commandMap.remove(name.toLowerCase(Locale.ROOT));
}
@Override
public boolean hasSubCommand(String name) {
return commandMap.containsKey(name.toLowerCase(Locale.ROOT));
@@ -194,5 +200,6 @@ public abstract class ViaCommandHandler implements ViaVersionCommand {
registerSubCommand(new DontBugMeSubCmd());
registerSubCommand(new AutoTeamSubCmd());
registerSubCommand(new ReloadSubCmd());
registerSubCommand(new PlayerSubCmd());
}
}
@@ -20,6 +20,9 @@ package com.viaversion.viaversion.commands.defaultsubs;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.command.ViaSubCommand;
import io.netty.util.ResourceLeakDetector;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class DisplayLeaksSubCmd implements ViaSubCommand {
@Override
@@ -33,13 +36,34 @@ public class DisplayLeaksSubCmd implements ViaSubCommand {
}
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
if (ResourceLeakDetector.getLevel() != ResourceLeakDetector.Level.PARANOID)
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.PARANOID);
else
ResourceLeakDetector.setLevel(ResourceLeakDetector.Level.DISABLED);
public String usage() {
return "displayleaks <level>";
}
sendMessage(sender, "&6Leak detector is now %s", (ResourceLeakDetector.getLevel() == ResourceLeakDetector.Level.PARANOID ? "&aenabled" : "&cdisabled"));
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
if (args.length == 1) {
try {
ResourceLeakDetector.Level level = ResourceLeakDetector.Level.valueOf(args[0]);
ResourceLeakDetector.setLevel(level);
sendMessage(sender, "&6Set leak detector level to &2" + level);
} catch (IllegalArgumentException e) {
sendMessage(sender, "&cInvalid level (" + Arrays.toString(ResourceLeakDetector.Level.values()) + ")");
}
} else {
sendMessage(sender, "&6Current leak detection level is &2" + ResourceLeakDetector.getLevel());
}
return true;
}
@Override
public List<String> onTabComplete(ViaCommandSender sender, String[] args) {
if (args.length == 1) {
return Arrays.stream(ResourceLeakDetector.Level.values())
.map(Enum::name)
.filter(it -> it.startsWith(args[0]))
.collect(Collectors.toList());
}
return ViaSubCommand.super.onTabComplete(sender, args);
}
}
@@ -20,6 +20,7 @@ package com.viaversion.viaversion.commands.defaultsubs;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.command.ViaSubCommand;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import java.util.HashSet;
import java.util.Map;
@@ -46,10 +47,9 @@ public class ListSubCmd implements ViaSubCommand {
public boolean execute(ViaCommandSender sender, String[] args) {
Map<ProtocolVersion, Set<String>> playerVersions = new TreeMap<>(ProtocolVersion::compareTo);
for (ViaCommandSender p : Via.getPlatform().getOnlinePlayers()) {
int playerVersion = Via.getAPI().getPlayerVersion(p.getUUID());
ProtocolVersion key = ProtocolVersion.getProtocol(playerVersion);
playerVersions.computeIfAbsent(key, s -> new HashSet<>()).add(p.getName());
for (UserConnection p : Via.getManager().getConnectionManager().getConnections()) {
ProtocolVersion version = p.getProtocolInfo().protocolVersion();
playerVersions.computeIfAbsent(version, s -> new HashSet<>()).add(p.getProtocolInfo().getUsername());
}
for (Map.Entry<ProtocolVersion, Set<String>> entry : playerVersions.entrySet()) {
@@ -46,26 +46,25 @@ public class PPSSubCmd implements ViaSubCommand {
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
Map<Integer, Set<String>> playerVersions = new HashMap<>();
Map<ProtocolVersion, Set<String>> playerVersions = new TreeMap<>(ProtocolVersion::compareTo);
int totalPackets = 0;
int clients = 0;
long max = 0;
for (ViaCommandSender p : Via.getPlatform().getOnlinePlayers()) {
int playerVersion = Via.getAPI().getPlayerVersion(p.getUUID());
if (!playerVersions.containsKey(playerVersion))
for (UserConnection p : Via.getManager().getConnectionManager().getConnections()) {
ProtocolVersion playerVersion = p.getProtocolInfo().protocolVersion();
if (!playerVersions.containsKey(playerVersion)) {
playerVersions.put(playerVersion, new HashSet<>());
UserConnection uc = Via.getManager().getConnectionManager().getConnectedClient(p.getUUID());
if (uc != null && uc.getPacketTracker().getPacketsPerSecond() > -1) {
playerVersions.get(playerVersion).add(p.getName() + " (" + uc.getPacketTracker().getPacketsPerSecond() + " PPS)");
totalPackets += uc.getPacketTracker().getPacketsPerSecond();
if (uc.getPacketTracker().getPacketsPerSecond() > max) {
max = uc.getPacketTracker().getPacketsPerSecond();
}
if (p.getPacketTracker().getPacketsPerSecond() > -1) {
playerVersions.get(playerVersion).add(p.getProtocolInfo().getUsername() + " (" + p.getPacketTracker().getPacketsPerSecond() + " PPS)");
totalPackets += p.getPacketTracker().getPacketsPerSecond();
if (p.getPacketTracker().getPacketsPerSecond() > max) {
max = p.getPacketTracker().getPacketsPerSecond();
}
clients++;
}
}
Map<Integer, Set<String>> sorted = new TreeMap<>(playerVersions);
sendMessage(sender, "&4Live Packets Per Second");
if (clients > 1) {
sendMessage(sender, "&cAverage: &f" + (totalPackets / clients));
@@ -74,9 +73,10 @@ public class PPSSubCmd implements ViaSubCommand {
if (clients == 0) {
sendMessage(sender, "&cNo clients to display.");
}
for (Map.Entry<Integer, Set<String>> entry : sorted.entrySet())
sendMessage(sender, "&8[&6%s&8]: &b%s", ProtocolVersion.getProtocol(entry.getKey()).getName(), entry.getValue());
sorted.clear();
for (Map.Entry<ProtocolVersion, Set<String>> entry : playerVersions.entrySet()) {
sendMessage(sender, "&8[&6%s&8]: &b%s", entry.getKey().getName(), entry.getValue());
}
playerVersions.clear();
return true;
}
}
@@ -0,0 +1,75 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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.commands.defaultsubs;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.command.ViaSubCommand;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.UserConnection;
import java.util.ArrayList;
import java.util.List;
public class PlayerSubCmd implements ViaSubCommand {
@Override
public String name() {
return "player";
}
@Override
public String description() {
return "Shows connection information about one or all players.";
}
@Override
public String usage() {
return "player <name|*>";
}
@Override
public boolean execute(final ViaCommandSender sender, final String[] args) {
if (args.length == 0) {
return false;
}
for (final UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final ProtocolInfo info = connection.getProtocolInfo();
if (args[0].equalsIgnoreCase(info.getUsername()) || args[0].equals("*")) {
sendMessage(sender, "&7[&6" + info.getUsername() + "&7] UUID: &2" + info.getUuid() + " &7Client-Protocol: &2" + info.protocolVersion().getName() + " &7Server-Protocol: &2" + info.serverProtocolVersion().getName());
}
}
return true;
}
@Override
public List<String> onTabComplete(final ViaCommandSender sender, final String[] args) {
if (args.length == 1) {
final String input = args[0].toLowerCase();
final List<String> matches = new ArrayList<>();
for (final UserConnection connection : Via.getManager().getConnectionManager().getConnections()) {
final String name = connection.getProtocolInfo().getUsername();
if (input.isEmpty() || name.toLowerCase().startsWith(input)) {
matches.add(name);
}
}
matches.add("*");
return matches;
}
return ViaSubCommand.super.onTabComplete(sender, args);
}
}
@@ -41,6 +41,7 @@ import com.viaversion.viaversion.protocol.packet.VersionedPacketTransformerImpl;
import com.viaversion.viaversion.protocols.base.BaseProtocol;
import com.viaversion.viaversion.protocols.base.BaseProtocol1_16;
import com.viaversion.viaversion.protocols.base.BaseProtocol1_7;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_10to1_11.Protocol1_10To1_11;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.Protocol1_11_1To1_12;
import com.viaversion.viaversion.protocols.v1_11to1_11_1.Protocol1_11To1_11_1;
@@ -187,6 +188,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
registerProtocol(new Protocol1_20To1_20_2(), ProtocolVersion.v1_20_2, ProtocolVersion.v1_20);
registerProtocol(new Protocol1_20_2To1_20_3(), ProtocolVersion.v1_20_3, ProtocolVersion.v1_20_2);
registerProtocol(new Protocol1_20_3To1_20_5(), ProtocolVersion.v1_20_5, ProtocolVersion.v1_20_3);
registerProtocol(new Protocol1_20_5To1_21(), ProtocolVersion.v1_21, ProtocolVersion.v1_20_5);
}
@Override
@@ -144,7 +144,6 @@ public class EntityMappings1_11 {
if (hasEntityTag(item)) {
toClient(item.tag().getCompoundTag("EntityTag"), backwards);
}
if (item != null && item.amount() <= 0) item.setAmount(1);
}
public static void toServerItem(Item item) {
@@ -17,9 +17,10 @@
*/
package com.viaversion.viaversion.protocols.v1_10to1_11.rewriter;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_10to1_11.Protocol1_10To1_11;
import com.viaversion.viaversion.protocols.v1_10to1_11.data.EntityMappings1_11;
@@ -38,45 +39,20 @@ public class ItemPacketRewriter1_11 extends ItemRewriter<ClientboundPackets1_9_3
registerSetSlot(ClientboundPackets1_9_3.CONTAINER_SET_SLOT);
registerSetContent(ClientboundPackets1_9_3.CONTAINER_SET_CONTENT);
registerSetEquippedItem(ClientboundPackets1_9_3.SET_EQUIPPED_ITEM);
// Plugin message Packet -> Trading
protocol.registerClientbound(ClientboundPackets1_9_3.CUSTOM_PAYLOAD, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // 0 - Channel
handlerSoftFail(wrapper -> {
if (wrapper.get(Types.STRING, 0).equals("MC|TrList")) {
wrapper.passthrough(Types.INT); // Passthrough Window ID
int size = wrapper.passthrough(Types.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_8)); // Input Item
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_8)); // Output Item
boolean secondItem = wrapper.passthrough(Types.BOOLEAN); // Has second item
if (secondItem) {
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_8)); // Second Item
}
wrapper.passthrough(Types.BOOLEAN); // Trade disabled
wrapper.passthrough(Types.INT); // Number of tools uses
wrapper.passthrough(Types.INT); // Maximum number of trade uses
}
}
});
}
});
registerCustomPayloadTradeList(ClientboundPackets1_9_3.CUSTOM_PAYLOAD);
registerContainerClick(ServerboundPackets1_9_3.CONTAINER_CLICK);
registerSetCreativeModeSlot(ServerboundPackets1_9_3.SET_CREATIVE_MODE_SLOT);
}
@Override
public Item handleItemToClient(UserConnection connection, Item item) {
if (item != null && item.isEmpty()) {
// Map empty items to null
return null;
if (item != null && item.amount() <= 0) {
CompoundTag tag = item.tag();
if (tag == null) {
item.setTag(tag = new CompoundTag());
}
tag.putByte(nbtTagName(), (byte) item.amount());
item.setAmount(1);
}
EntityMappings1_11.toClientItem(item);
return item;
@@ -84,8 +60,16 @@ public class ItemPacketRewriter1_11 extends ItemRewriter<ClientboundPackets1_9_3
@Override
public Item handleItemToServer(UserConnection connection, Item item) {
if (item == null) {
return null;
}
if (item.tag() != null && item.tag().contains(nbtTagName())) {
item.setAmount(item.tag().<ByteTag>removeUnchecked(nbtTagName()).asByte());
if (item.tag().isEmpty()) {
item.setTag(null);
}
}
EntityMappings1_11.toServerItem(item);
if (item == null) return null;
boolean newItem = item.identifier() >= 218 && item.identifier() <= 234;
newItem |= item.identifier() == 449 || item.identifier() == 450;
if (newItem) { // Replace server-side unknown items
@@ -40,36 +40,7 @@ public class ItemPacketRewriter1_12 extends ItemRewriter<ClientboundPackets1_9_3
registerSetSlot(ClientboundPackets1_9_3.CONTAINER_SET_SLOT);
registerSetContent(ClientboundPackets1_9_3.CONTAINER_SET_CONTENT);
registerSetEquippedItem(ClientboundPackets1_9_3.SET_EQUIPPED_ITEM);
// Plugin message -> Trading
protocol.registerClientbound(ClientboundPackets1_9_3.CUSTOM_PAYLOAD, new PacketHandlers() {
@Override
public void register() {
map(Types.STRING); // 0 - Channel
handlerSoftFail(wrapper -> {
if (wrapper.get(Types.STRING, 0).equals("MC|TrList")) {
wrapper.passthrough(Types.INT); // Passthrough Window ID
int size = wrapper.passthrough(Types.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_8)); // Input Item
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_8)); // Output Item
boolean secondItem = wrapper.passthrough(Types.BOOLEAN); // Has second item
if (secondItem) {
handleItemToClient(wrapper.user(), wrapper.passthrough(Types.ITEM1_8)); // Second Item
}
wrapper.passthrough(Types.BOOLEAN); // Trade disabled
wrapper.passthrough(Types.INT); // Number of tools uses
wrapper.passthrough(Types.INT); // Maximum number of trade uses
}
}
});
}
});
registerCustomPayloadTradeList(ClientboundPackets1_9_3.CUSTOM_PAYLOAD);
protocol.registerServerbound(ServerboundPackets1_12.CONTAINER_CLICK, new PacketHandlers() {
@Override
@@ -28,7 +28,7 @@ import com.viaversion.viaversion.rewriter.ItemRewriter;
public class ItemPacketRewriter1_11_1 extends ItemRewriter<ClientboundPackets1_9_3, ServerboundPackets1_9_3, Protocol1_11To1_11_1> {
public ItemPacketRewriter1_11_1(Protocol1_11To1_11_1 protocol) {
super(protocol, Types.ITEM1_8, null);
super(protocol, Types.ITEM1_8, Types.ITEM1_8_SHORT_ARRAY);
}
@Override
@@ -51,7 +51,7 @@ import java.util.Optional;
public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_1, ServerboundPackets1_13, Protocol1_12_2To1_13> {
public ItemPacketRewriter1_13(Protocol1_12_2To1_13 protocol) {
super(protocol, null, null);
super(protocol, Types.ITEM1_8, Types.ITEM1_8_SHORT_ARRAY, Types.ITEM1_13, Types.ITEM1_13_SHORT_ARRAY);
}
@Override
@@ -136,31 +136,7 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
return;
} else if (channel.equals("MC|TrList")) {
channel = "minecraft:trader_list";
wrapper.passthrough(Types.INT); // Passthrough Window ID
int size = wrapper.passthrough(Types.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
// Input Item
Item input = wrapper.read(Types.ITEM1_8);
handleItemToClient(wrapper.user(), input);
wrapper.write(Types.ITEM1_13, input);
// Output Item
Item output = wrapper.read(Types.ITEM1_8);
handleItemToClient(wrapper.user(), output);
wrapper.write(Types.ITEM1_13, output);
boolean secondItem = wrapper.passthrough(Types.BOOLEAN); // Has second item
if (secondItem) {
// Second Item
Item second = wrapper.read(Types.ITEM1_8);
handleItemToClient(wrapper.user(), second);
wrapper.write(Types.ITEM1_13, second);
}
wrapper.passthrough(Types.BOOLEAN); // Trade disabled
wrapper.passthrough(Types.INT); // Number of tools uses
wrapper.passthrough(Types.INT); // Maximum number of trade uses
}
handleTradeList(wrapper);
} else {
String old = channel;
channel = getNewPluginChannelId(channel);
@@ -353,7 +353,7 @@ public final class Protocol1_20_2To1_20_3 extends AbstractProtocol<ClientboundPa
.reader("dust", ParticleType.Readers.DUST)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION)
.reader("item", ParticleType.Readers.ITEM1_20_2)
.reader("item", ParticleType.Readers.item(Types.ITEM1_20_2))
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK);
@@ -253,7 +253,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
.reader("dust_pillar", ParticleType.Readers.BLOCK)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION)
.reader("item", ParticleType.Readers.ITEM1_20_5)
.reader("item", ParticleType.Readers.item(Types1_20_5.ITEM))
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK)
@@ -261,21 +261,21 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
Types1_20_5.STRUCTURED_DATA.filler(this)
.add(StructuredDataKey.CUSTOM_DATA).add(StructuredDataKey.MAX_STACK_SIZE).add(StructuredDataKey.MAX_DAMAGE)
.add(StructuredDataKey.DAMAGE).add(StructuredDataKey.UNBREAKABLE).add(StructuredDataKey.RARITY)
.add(StructuredDataKey.HIDE_TOOLTIP).add(StructuredDataKey.FOOD).add(StructuredDataKey.FIRE_RESISTANT)
.add(StructuredDataKey.HIDE_TOOLTIP).add(StructuredDataKey.FOOD1_20_5).add(StructuredDataKey.FIRE_RESISTANT)
.add(StructuredDataKey.CUSTOM_NAME).add(StructuredDataKey.LORE).add(StructuredDataKey.ENCHANTMENTS)
.add(StructuredDataKey.CAN_PLACE_ON).add(StructuredDataKey.CAN_BREAK).add(StructuredDataKey.ATTRIBUTE_MODIFIERS)
.add(StructuredDataKey.CAN_PLACE_ON).add(StructuredDataKey.CAN_BREAK).add(StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5)
.add(StructuredDataKey.CUSTOM_MODEL_DATA).add(StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP).add(StructuredDataKey.REPAIR_COST)
.add(StructuredDataKey.CREATIVE_SLOT_LOCK).add(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE).add(StructuredDataKey.INTANGIBLE_PROJECTILE)
.add(StructuredDataKey.STORED_ENCHANTMENTS).add(StructuredDataKey.DYED_COLOR).add(StructuredDataKey.MAP_COLOR)
.add(StructuredDataKey.MAP_ID).add(StructuredDataKey.MAP_DECORATIONS).add(StructuredDataKey.MAP_POST_PROCESSING)
.add(StructuredDataKey.CHARGED_PROJECTILES).add(StructuredDataKey.BUNDLE_CONTENTS).add(StructuredDataKey.POTION_CONTENTS)
.add(StructuredDataKey.CHARGED_PROJECTILES1_20_5).add(StructuredDataKey.BUNDLE_CONTENTS1_20_5).add(StructuredDataKey.POTION_CONTENTS)
.add(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS).add(StructuredDataKey.WRITABLE_BOOK_CONTENT).add(StructuredDataKey.WRITTEN_BOOK_CONTENT)
.add(StructuredDataKey.TRIM).add(StructuredDataKey.DEBUG_STICK_STATE).add(StructuredDataKey.ENTITY_DATA)
.add(StructuredDataKey.BUCKET_ENTITY_DATA).add(StructuredDataKey.BLOCK_ENTITY_DATA).add(StructuredDataKey.INSTRUMENT)
.add(StructuredDataKey.RECIPES).add(StructuredDataKey.LODESTONE_TRACKER).add(StructuredDataKey.FIREWORK_EXPLOSION)
.add(StructuredDataKey.FIREWORKS).add(StructuredDataKey.PROFILE).add(StructuredDataKey.NOTE_BLOCK_SOUND)
.add(StructuredDataKey.BANNER_PATTERNS).add(StructuredDataKey.BASE_COLOR).add(StructuredDataKey.POT_DECORATIONS)
.add(StructuredDataKey.CONTAINER).add(StructuredDataKey.BLOCK_STATE).add(StructuredDataKey.BEES)
.add(StructuredDataKey.CONTAINER1_20_5).add(StructuredDataKey.BLOCK_STATE).add(StructuredDataKey.BEES)
.add(StructuredDataKey.LOCK).add(StructuredDataKey.CONTAINER_LOOT).add(StructuredDataKey.TOOL)
.add(StructuredDataKey.ITEM_NAME).add(StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER);
@@ -47,8 +47,9 @@ 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.ArmorTrimPattern;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifier;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5.AttributeModifier;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5.ModifierData;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPattern;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
@@ -64,7 +65,6 @@ import com.viaversion.viaversion.api.minecraft.item.data.FoodEffect;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.ModifierData;
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.PotionEffect;
@@ -294,7 +294,9 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
protocol.getEntityRewriter().rewriteParticle(wrapper, Types1_20_3.PARTICLE, Types1_20_5.PARTICLE); // Small explosion particle
protocol.getEntityRewriter().rewriteParticle(wrapper, Types1_20_3.PARTICLE, Types1_20_5.PARTICLE); // Large explosion particle
wrapper.write(Types.VAR_INT, 0); // "Empty" registry id to instead use the resource location that follows after
final String sound = wrapper.read(Types.STRING);
final Float range = wrapper.read(Types.OPTIONAL_FLOAT);
wrapper.write(Types.SOUND_EVENT, Holder.of(new SoundEvent(sound, range)));
});
protocol.registerClientbound(ClientboundPackets1_20_3.MERCHANT_OFFERS, wrapper -> {
@@ -340,7 +342,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
wrapper.passthrough(Types.STRING); // Recipe Identifier
wrapper.write(Types.VAR_INT, protocol.getMappingData().getRecipeSerializerMappings().mappedId(type));
recipeRewriter.handleRecipeType(wrapper, Key.stripMinecraftNamespace(type));
recipeRewriter.handleRecipeType(wrapper, type);
}
});
}
@@ -355,7 +357,12 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
}
@Override
public Item handleItemToClient(final UserConnection connection, final Item item) {
public Item handleItemToClient(final UserConnection connection, @Nullable final Item item) {
if (item == null) {
// We no longer want null items, always unify them to empty
return StructuredItem.empty();
}
// Add the original as custom data, to be re-used for creative clients as well
final CompoundTag tag = item.tag();
if (tag != null) {
@@ -375,7 +382,12 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
}
@Override
public Item handleItemToServer(UserConnection connection, final Item item) {
public @Nullable Item handleItemToServer(UserConnection connection, final Item item) {
if (item.isEmpty()) {
// Empty to null for the old protocols
return null;
}
super.handleItemToServer(connection, item);
return toOldItem(connection, item, DATA_CONVERTER);
}
@@ -442,6 +454,8 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
entityTag = entityTag.copy();
if (entityTag.contains("variant")) {
entityTag.putString("id", "minecraft:painting");
} else if (entityTag.contains("ShowArms")) {
entityTag.putString("id", "minecraft:armor_stand");
}
data.set(StructuredDataKey.ENTITY_DATA, entityTag);
}
@@ -503,7 +517,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
if (attributeModifiersTag != null) {
updateAttributes(data, attributeModifiersTag, showAttributes);
} else if (!showAttributes) {
data.set(StructuredDataKey.ATTRIBUTE_MODIFIERS, new AttributeModifiers(new AttributeModifier[0], false));
data.set(StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5, new AttributeModifiers1_20_5(new AttributeModifier[0], false));
}
final CompoundTag fireworksTag = tag.getCompoundTag("Fireworks");
@@ -522,9 +536,9 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
updateMobTags(data, tag);
updateItemList(connection, data, tag, "ChargedProjectiles", StructuredDataKey.CHARGED_PROJECTILES, false);
updateItemList(connection, data, tag, "ChargedProjectiles", StructuredDataKey.CHARGED_PROJECTILES1_20_5, false);
if (old.identifier() == 927) {
updateItemList(connection, data, tag, "Items", StructuredDataKey.BUNDLE_CONTENTS, false);
updateItemList(connection, data, tag, "Items", StructuredDataKey.BUNDLE_CONTENTS1_20_5, false);
}
updateEnchantments(data, tag, "Enchantments", StructuredDataKey.ENCHANTMENTS, (hideFlagsValue & StructuredDataConverter.HIDE_ENCHANTMENTS) == 0);
@@ -700,7 +714,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
effect.getFloat("probability")
));
}
data.set(StructuredDataKey.FOOD, new FoodProperties(nutrition, saturation, canAlwaysEat, eatSeconds, possibleEffects.toArray(new FoodEffect[0])));
data.set(StructuredDataKey.FOOD1_20_5, new FoodProperties(nutrition, saturation, canAlwaysEat, eatSeconds, null, possibleEffects.toArray(new FoodEffect[0])));
}
private void restoreToolFromBackup(final CompoundTag tool, final StructuredDataContainer data) {
@@ -862,7 +876,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
slotTypeId
));
}
data.set(StructuredDataKey.ATTRIBUTE_MODIFIERS, new AttributeModifiers(modifiers.toArray(new AttributeModifier[0]), showInTooltip));
data.set(StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5, new AttributeModifiers1_20_5(modifiers.toArray(new AttributeModifier[0]), showInTooltip));
}
private PotionEffectData readPotionEffectData(final CompoundTag tag) {
@@ -1182,12 +1196,12 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
private Item itemFromTag(final UserConnection connection, final CompoundTag item) {
final String id = item.getString("id");
if (id == null) {
return null;
return StructuredItem.empty();
}
final int itemId = StructuredDataConverter.removeItemBackupTag(item, unmappedItemId(id));
if (itemId == -1) {
return null;
return StructuredItem.empty();
}
final byte count = item.getByte("Count", (byte) 1);
@@ -1429,7 +1443,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
data.set(StructuredDataKey.BASE_COLOR, baseColorIntTag.asInt());
}
updateItemList(connection, data, tag, "Items", StructuredDataKey.CONTAINER, true);
updateItemList(connection, data, tag, "Items", StructuredDataKey.CONTAINER1_20_5, true);
}
final Tag skullOwnerTag = tag.remove("SkullOwner");
@@ -41,8 +41,9 @@ 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.ArmorTrimPattern;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifier;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5.AttributeModifier;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5.ModifierData;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPattern;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
@@ -58,7 +59,6 @@ import com.viaversion.viaversion.api.minecraft.item.data.FoodEffect;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.ModifierData;
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.PotionEffect;
@@ -126,7 +126,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.ENCHANTMENTS, this::convertEnchantments);
register(StructuredDataKey.CAN_PLACE_ON, this::convertCanPlaceOn);
register(StructuredDataKey.CAN_BREAK, this::convertCanBreak);
register(StructuredDataKey.ATTRIBUTE_MODIFIERS, this::convertAttributeModifiers);
register(StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5, this::convertAttributeModifiers);
register(StructuredDataKey.CUSTOM_MODEL_DATA, this::convertCustomModelData);
register(StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP, this::convertHideAdditionalTooltip);
register(StructuredDataKey.HIDE_TOOLTIP, this::convertHideTooltip);
@@ -134,7 +134,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, this::convertEnchantmentGlintOverride);
register(StructuredDataKey.CREATIVE_SLOT_LOCK, null);
register(StructuredDataKey.INTANGIBLE_PROJECTILE, this::convertIntangibleProjectile);
register(StructuredDataKey.FOOD, this::convertFood);
register(StructuredDataKey.FOOD1_20_5, this::convertFood);
register(StructuredDataKey.FIRE_RESISTANT, this::convertFireResistant);
register(StructuredDataKey.TOOL, this::convertTool);
register(StructuredDataKey.STORED_ENCHANTMENTS, this::convertStoredEnchantments);
@@ -143,8 +143,8 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.MAP_ID, this::convertMapId);
register(StructuredDataKey.MAP_DECORATIONS, this::convertMapDecorations);
register(StructuredDataKey.MAP_POST_PROCESSING, null);
register(StructuredDataKey.CHARGED_PROJECTILES, this::convertChargedProjectiles);
register(StructuredDataKey.BUNDLE_CONTENTS, this::convertBundleContents);
register(StructuredDataKey.CHARGED_PROJECTILES1_20_5, this::convertChargedProjectiles);
register(StructuredDataKey.BUNDLE_CONTENTS1_20_5, this::convertBundleContents);
register(StructuredDataKey.POTION_CONTENTS, this::convertPotionContents);
register(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, this::convertSuspiciousStewEffects);
register(StructuredDataKey.WRITABLE_BOOK_CONTENT, this::convertWritableBookContent);
@@ -165,7 +165,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
register(StructuredDataKey.BANNER_PATTERNS, this::convertBannerPatterns);
register(StructuredDataKey.BASE_COLOR, this::convertBaseColor);
register(StructuredDataKey.POT_DECORATIONS, this::convertPotDecorations);
register(StructuredDataKey.CONTAINER, this::convertContainer);
register(StructuredDataKey.CONTAINER1_20_5, this::convertContainer);
register(StructuredDataKey.BLOCK_STATE, this::convertBlockState);
register(StructuredDataKey.BEES, this::convertBees);
register(StructuredDataKey.LOCK, this::convertLock);
@@ -446,7 +446,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
return convertCanPlaceOn(value);
}
protected CompoundTag convertAttributeModifiers(final AttributeModifiers value) {
protected CompoundTag convertAttributeModifiers(final AttributeModifiers1_20_5 value) {
final CompoundTag tag = new CompoundTag();
final ListTag<CompoundTag> modifiers = new ListTag<>(CompoundTag.class);
for (final AttributeModifier modifier : value.modifiers()) {
@@ -412,13 +412,12 @@ public final class EntityPacketRewriter1_20_5 extends EntityRewriter<Clientbound
Types1_20_5.ENTITY_DATA_TYPES.blockStateType,
Types1_20_5.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_20_5.ENTITY_DATA_TYPES.particleType,
null
null,
Types1_20_5.ENTITY_DATA_TYPES.componentType,
Types1_20_5.ENTITY_DATA_TYPES.optionalComponentType
);
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
filter().dataType(Types1_20_5.ENTITY_DATA_TYPES.componentType).handler((event, meta) -> protocol.getComponentRewriter().processTag(event.user(), meta.value()));
filter().dataType(Types1_20_5.ENTITY_DATA_TYPES.optionalComponentType).handler((event, meta) -> protocol.getComponentRewriter().processTag(event.user(), meta.value()));
filter().type(EntityTypes1_20_5.LIVING_ENTITY).index(10).handler((event, meta) -> {
final int effectColor = meta.value();
if (effectColor == 0) {
@@ -35,7 +35,7 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.AdventureModePredicate;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrimPattern;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifier;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5.AttributeModifier;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPattern;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
@@ -128,7 +128,7 @@ public final class StructuredDataConverter {
});
register(StructuredDataKey.ENCHANTMENTS, (data, tag) -> convertEnchantments(data, tag, false));
register(StructuredDataKey.STORED_ENCHANTMENTS, (data, tag) -> convertEnchantments(data, tag, true));
register(StructuredDataKey.ATTRIBUTE_MODIFIERS, (data, tag) -> {
register(StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5, (data, tag) -> {
final ListTag<CompoundTag> modifiers = new ListTag<>(CompoundTag.class);
for (int i = 0; i < data.modifiers().length; i++) {
final AttributeModifier modifier = data.modifiers()[i];
@@ -218,8 +218,8 @@ public final class StructuredDataConverter {
}
});
register(StructuredDataKey.BASE_COLOR, (data, tag) -> getBlockEntityTag(tag).putInt("Base", data));
register(StructuredDataKey.CHARGED_PROJECTILES, (connection, data, tag) -> convertItemList(connection, data, tag, "ChargedProjectiles"));
register(StructuredDataKey.BUNDLE_CONTENTS, (connection, data, tag) -> convertItemList(connection, data, tag, "Items"));
register(StructuredDataKey.CHARGED_PROJECTILES1_20_5, (connection, data, tag) -> convertItemList(connection, data, tag, "ChargedProjectiles"));
register(StructuredDataKey.BUNDLE_CONTENTS1_20_5, (connection, data, tag) -> convertItemList(connection, data, tag, "Items"));
register(StructuredDataKey.LODESTONE_TRACKER, (data, tag) -> {
tag.putBoolean("LodestoneTracked", data.tracked());
if (data.position() != null) {
@@ -494,7 +494,7 @@ public final class StructuredDataConverter {
}
getBlockEntityTag(tag, "banner").put("Patterns", patternsTag);
});
register(StructuredDataKey.CONTAINER, (connection, data, tag) -> convertItemList(connection, data, getBlockEntityTag(tag), "Items"));
register(StructuredDataKey.CONTAINER1_20_5, (connection, data, tag) -> convertItemList(connection, data, getBlockEntityTag(tag), "Items"));
register(StructuredDataKey.CAN_PLACE_ON, (data, tag) -> convertBlockPredicates(tag, data, "CanPlaceOn", HIDE_CAN_PLACE_ON));
register(StructuredDataKey.CAN_BREAK, (data, tag) -> convertBlockPredicates(tag, data, "CanDestroy", HIDE_CAN_DESTROY));
register(StructuredDataKey.MAP_POST_PROCESSING, (data, tag) -> {
@@ -596,7 +596,7 @@ public final class StructuredDataConverter {
getBackupTag(tag).putInt("rarity", data);
}
});
register(StructuredDataKey.FOOD, (data, tag) -> {
register(StructuredDataKey.FOOD1_20_5, (data, tag) -> {
if (backupInconvertibleData) {
final CompoundTag backupTag = new CompoundTag();
backupTag.putInt("nutrition", data.nutrition());
@@ -0,0 +1,261 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21;
import com.viaversion.viaversion.api.connection.UserConnection;
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_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.ChatType;
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;
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_21;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.AttributeModifierMappings1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.MappingData1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacketRewriter1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.ComponentRewriter1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.EntityPacketRewriter1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.UUIDUtil;
import java.util.Locale;
import java.util.UUID;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPacket1_20_5, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
public static final MappingData1_21 MAPPINGS = new MappingData1_21();
private final EntityPacketRewriter1_21 entityRewriter = new EntityPacketRewriter1_21(this);
private final BlockItemPacketRewriter1_21 itemRewriter = new BlockItemPacketRewriter1_21(this);
private final TagRewriter<ClientboundPacket1_20_5> tagRewriter = new TagRewriter<>(this);
private final ComponentRewriter<ClientboundPacket1_20_5> componentRewriter = new ComponentRewriter1_21(this);
public Protocol1_20_5To1_21() {
super(ClientboundPacket1_20_5.class, ClientboundPacket1_21.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
tagRewriter.registerGeneric(ClientboundPackets1_20_5.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_20_5.UPDATE_TAGS);
final SoundRewriter<ClientboundPacket1_20_5> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND_ENTITY);
new StatisticsRewriter<>(this).register(ClientboundPackets1_20_5.AWARD_STATS);
componentRewriter.registerOpenScreen(ClientboundPackets1_20_5.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_5.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_5.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_5.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets1_20_5.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_5.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets1_20_5.TAB_LIST);
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_20_5.PLAYER_COMBAT_KILL);
componentRewriter.registerComponentPacket(ClientboundPackets1_20_5.SYSTEM_CHAT);
registerClientbound(ClientboundPackets1_20_5.DISGUISED_CHAT, wrapper -> {
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.TAG)); // Message
// Holder time
final int chatType = wrapper.read(Types.VAR_INT);
wrapper.write(ChatType.TYPE, Holder.of(chatType));
});
registerClientbound(ClientboundPackets1_20_5.PLAYER_CHAT, wrapper -> {
wrapper.passthrough(Types.UUID); // Sender
wrapper.passthrough(Types.VAR_INT); // Index
wrapper.passthrough(Types.OPTIONAL_SIGNATURE_BYTES); // Signature
wrapper.passthrough(Types.STRING); // Plain content
wrapper.passthrough(Types.LONG); // Timestamp
wrapper.passthrough(Types.LONG); // Salt
final int lastSeen = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < lastSeen; i++) {
final int index = wrapper.passthrough(Types.VAR_INT);
if (index == 0) {
wrapper.passthrough(Types.SIGNATURE_BYTES);
}
}
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.OPTIONAL_TAG)); // Unsigned content
final int filterMaskType = wrapper.passthrough(Types.VAR_INT);
if (filterMaskType == 2) {
wrapper.passthrough(Types.LONG_ARRAY_PRIMITIVE); // Mask
}
final int chatType = wrapper.read(Types.VAR_INT);
wrapper.write(ChatType.TYPE, Holder.of(chatType));
});
registerClientbound(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
final int size = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < size; i++) {
final int attributeId = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT, MAPPINGS.getNewAttributeId(attributeId));
wrapper.passthrough(Types.DOUBLE); // Base
final int modifierSize = wrapper.passthrough(Types.VAR_INT);
for (int j = 0; j < modifierSize; j++) {
final UUID uuid = wrapper.read(Types.UUID);
wrapper.write(Types.STRING, mapAttributeUUID(uuid, null));
wrapper.passthrough(Types.DOUBLE); // Amount
wrapper.passthrough(Types.BYTE); // Operation
}
}
});
registerClientbound(ClientboundPackets1_20_5.PROJECTILE_POWER, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Id
final double xPower = wrapper.read(Types.DOUBLE);
final double yPower = wrapper.read(Types.DOUBLE);
final double zPower = wrapper.read(Types.DOUBLE);
final double accelerationPower = Math.sqrt(xPower * xPower + yPower * yPower + zPower * zPower);
wrapper.write(Types.DOUBLE, accelerationPower);
});
}
public static String mapAttributeUUID(final UUID uuid, final String name) {
String id = AttributeModifierMappings1_21.uuidToId(uuid);
if (id != null) {
return id;
}
if (name != null) {
id = AttributeModifierMappings1_21.nameToId(name);
}
return id != null ? id : uuid.toString().toLowerCase(Locale.ROOT);
}
public static UUID mapAttributeId(final String id) {
UUID uuid = AttributeModifierMappings1_21.idToUuid(id);
if (uuid != null) {
return uuid;
}
uuid = UUIDUtil.parseUUID(Key.stripNamespace(id).toUpperCase(Locale.ROOT));
return uuid != null ? uuid : UUID.randomUUID();
}
@Override
protected void onMappingDataLoaded() {
super.onMappingDataLoaded();
Types1_21.PARTICLE.filler(this)
.reader("block", ParticleType.Readers.BLOCK)
.reader("block_marker", ParticleType.Readers.BLOCK)
.reader("dust", ParticleType.Readers.DUST)
.reader("dust_pillar", ParticleType.Readers.BLOCK)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION)
.reader("item", ParticleType.Readers.item(Types1_21.ITEM))
.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);
Types1_21.STRUCTURED_DATA.filler(this)
.add(StructuredDataKey.CUSTOM_DATA).add(StructuredDataKey.MAX_STACK_SIZE).add(StructuredDataKey.MAX_DAMAGE)
.add(StructuredDataKey.DAMAGE).add(StructuredDataKey.UNBREAKABLE).add(StructuredDataKey.RARITY)
.add(StructuredDataKey.HIDE_TOOLTIP).add(StructuredDataKey.FIRE_RESISTANT)
.add(StructuredDataKey.CUSTOM_NAME).add(StructuredDataKey.LORE).add(StructuredDataKey.ENCHANTMENTS)
.add(StructuredDataKey.CAN_PLACE_ON).add(StructuredDataKey.CAN_BREAK)
.add(StructuredDataKey.CUSTOM_MODEL_DATA).add(StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP).add(StructuredDataKey.REPAIR_COST)
.add(StructuredDataKey.CREATIVE_SLOT_LOCK).add(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE).add(StructuredDataKey.INTANGIBLE_PROJECTILE)
.add(StructuredDataKey.STORED_ENCHANTMENTS).add(StructuredDataKey.DYED_COLOR).add(StructuredDataKey.MAP_COLOR)
.add(StructuredDataKey.MAP_ID).add(StructuredDataKey.MAP_DECORATIONS).add(StructuredDataKey.MAP_POST_PROCESSING)
.add(StructuredDataKey.CHARGED_PROJECTILES1_21).add(StructuredDataKey.BUNDLE_CONTENTS1_21).add(StructuredDataKey.POTION_CONTENTS)
.add(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS).add(StructuredDataKey.WRITABLE_BOOK_CONTENT).add(StructuredDataKey.WRITTEN_BOOK_CONTENT)
.add(StructuredDataKey.TRIM).add(StructuredDataKey.DEBUG_STICK_STATE).add(StructuredDataKey.ENTITY_DATA)
.add(StructuredDataKey.BUCKET_ENTITY_DATA).add(StructuredDataKey.BLOCK_ENTITY_DATA).add(StructuredDataKey.INSTRUMENT)
.add(StructuredDataKey.RECIPES).add(StructuredDataKey.LODESTONE_TRACKER).add(StructuredDataKey.FIREWORK_EXPLOSION)
.add(StructuredDataKey.FIREWORKS).add(StructuredDataKey.PROFILE).add(StructuredDataKey.NOTE_BLOCK_SOUND)
.add(StructuredDataKey.BANNER_PATTERNS).add(StructuredDataKey.BASE_COLOR).add(StructuredDataKey.POT_DECORATIONS)
.add(StructuredDataKey.CONTAINER1_21).add(StructuredDataKey.BLOCK_STATE).add(StructuredDataKey.BEES)
.add(StructuredDataKey.LOCK).add(StructuredDataKey.CONTAINER_LOOT).add(StructuredDataKey.TOOL)
.add(StructuredDataKey.ITEM_NAME).add(StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER)
.add(StructuredDataKey.FOOD1_21).add(StructuredDataKey.JUKEBOX_PLAYABLE).add(StructuredDataKey.ATTRIBUTE_MODIFIERS1_21);
tagRewriter.addEmptyTags(RegistryType.BLOCK, "minecraft:blocks_wind_charge_explosions");
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
}
@Override
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
connection.put(new EfficiencyAttributeStorage());
}
@Override
public MappingData1_21 getMappingData() {
return MAPPINGS;
}
@Override
public EntityPacketRewriter1_21 getEntityRewriter() {
return entityRewriter;
}
@Override
public BlockItemPacketRewriter1_21 getItemRewriter() {
return itemRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_20_5> getTagRewriter() {
return tagRewriter;
}
@Override
public ComponentRewriter<ClientboundPacket1_20_5> getComponentRewriter() {
return componentRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_20_5, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
@@ -0,0 +1,103 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.data;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.viaversion.viaversion.util.Key;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class AttributeModifierMappings1_21 {
private static final Map<UUID, String> ATTRIBUTE_MODIFIER_IDS = new HashMap<>();
private static final Map<String, UUID> ATTRIBUTE_MODIFIER_INVERSE_IDS = new HashMap<>();
private static final BiMap<String, String> ATTRIBUTE_MODIFIER_NAMES = HashBiMap.create(Map.of(
"Random spawn bonus", "random_spawn_bonus",
"Random zombie-spawn bonus", "zombie_random_spawn_bonus",
"Leader zombie bonus", "leader_zombie_bonus",
"Zombie reinforcement callee charge", "reinforcement_callee_charge",
"Zombie reinforcement caller charge", "reinforcement_caller_charge"
));
static {
add(-4483571535397864886L, -5989644940537681742L, "armor.body");
add(8144722948526719024L, -7778190119041365872L, "effect.slowness");
add(6967552254039378640L, -9116175396973475259L, "enchantment.aqua_affinity");
add(5279725409867744698L, -5150363631200102632L, "attacking");
add(148071211714102867L, -7685811609035173472L, "attacking");
add(6196088217904236654L, -7493791321850887290L, "effect.minining_fatigue");
add(-5084161844451524480L, -8859020046251006329L, "enchantment.soul_speed");
add(-7907339078496465106L, -8112074600724210224L, "enchantment.swift_sneak");
add(6688265815086220243L, -6545541163342161890L, "drinking");
add(8315164243412860989L, -6631520853640075966L, "creative_mode_block_range");
add(4389663563256579765L, -4827163546944004714L, "enchantment.efficiency");
add(6732612758648800940L, -5145707699103688244L, "effect.health_boost");
add(9079981369298536661L, -6728494925450710401L, "covered");
add(-1521481167610687786L, -8630419745734927691L, "effect.absorption");
add(-7473408062188862076L, -5872005994337939597L, "creative_mode_entity_range");
add(-3721396875562958315L, -5317020504214661337L, "effect.unluck");
add(-2861585646493481178L, -6113244764726669811L, "armor.leggings");
add(6718535547217657911L, -5386630269401489641L, "enchantment.sweeping_edge");
add(-7949229004988660584L, -7828611303000832459L, "effect.speed");
add(-8650171790042118250L, -5749650997644763080L, "enchantment.soul_speed");
add(551224288813600377L, -8734740027710371860L, "enchantment.respiration");
add(-7046399332347654691L, -6723081531683397260L, "suffocating");
add(7361814797886573596L, -8641397326606817395L, "sprinting");
add(-6972338111383059132L, -8978659762232839026L, "armor.chestplate");
add(-5371971015925809039L, -6062243582569928137L, "enchantment.fire_protection");
add(7245570952092733273L, -8449101711440750679L, "effect.strength");
add(-422425648963762075L, -5756800103171642205L, "base_attack_speed");
add(-4607081316629330256L, -7008565754814018370L, "effect.jump_boost");
add(271280981090454338L, -8746077033958322898L, "effect.luck");
add(2211131075215181206L, -5513857709499300658L, "powder_snow");
add(-8908768238899017377L, -8313820693701227669L, "armor.boots");
add(-5797418877589107702L, -6181652684028920077L, "effect.haste");
add(3086076556416732775L, -5150312587563650736L, "armor.helmet");
add(-5082757096938257406L, -4891139119377885130L, "baby");
add(2478452629826324956L, -7247530463494186011L, "effect.weakness");
add(4659420831966187055L, -5191473055587376048L, "enchantment.blast_protection");
add(7301951777949303281L, -6753860660653972126L, "evil");
add(8533189226688352746L, -8254757081029716377L, "baby");
add(1286946037536540352L, -5768092872487507967L, "enchantment.depth_strider");
add(-3801225194067177672L, -6586624321849018929L, "base_attack_damage");
}
public static @Nullable String uuidToId(final UUID uuid) {
return ATTRIBUTE_MODIFIER_IDS.get(uuid);
}
public static @Nullable UUID idToUuid(final String id) {
return ATTRIBUTE_MODIFIER_INVERSE_IDS.get(Key.stripMinecraftNamespace(id));
}
public static @Nullable String nameToId(final String name) {
return ATTRIBUTE_MODIFIER_NAMES.get(name);
}
public static @Nullable String idToName(final String id) {
return ATTRIBUTE_MODIFIER_NAMES.inverse().get(id);
}
private static void add(final long msb, final long lsb, final String id) {
final UUID uuid = new UUID(msb, lsb);
ATTRIBUTE_MODIFIER_IDS.put(uuid, id);
ATTRIBUTE_MODIFIER_INVERSE_IDS.put(id, uuid);
}
}
@@ -0,0 +1,57 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import java.util.Map;
public final class MappingData1_21 extends MappingDataBase {
private ListTag<CompoundTag> enchantments;
private CompoundTag jukeboxSongs;
public MappingData1_21() {
super("1.20.5", "1.21");
}
@Override
protected void loadExtras(final CompoundTag data) {
final CompoundTag extraMappings = MappingDataLoader.INSTANCE.loadNBT("enchantments-1.21.nbt");
enchantments = extraMappings.getListTag("entries", CompoundTag.class);
jukeboxSongs = MappingDataLoader.INSTANCE.loadNBT("jukebox-songs-1.21.nbt");
}
public CompoundTag enchantment(final int id) {
return enchantments.get(id).copy();
}
public RegistryEntry[] jukeboxSongs() {
final RegistryEntry[] entries = new RegistryEntry[jukeboxSongs.size()];
int i = 0;
for (final Map.Entry<String, Tag> entry : jukeboxSongs.entrySet()) {
final CompoundTag tag = (CompoundTag) entry.getValue();
entries[i++] = new RegistryEntry(entry.getKey(), tag.copy());
}
return entries;
}
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.data;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
public final class Paintings1_20_5 {
public static final PaintingVariant[] PAINTINGS = {
new PaintingVariant(1, 1, "kebab"),
new PaintingVariant(1, 1, "aztec"),
new PaintingVariant(1, 1, "alban"),
new PaintingVariant(1, 1, "aztec2"),
new PaintingVariant(1, 1, "bomb"),
new PaintingVariant(1, 1, "plant"),
new PaintingVariant(1, 1, "wasteland"),
new PaintingVariant(2, 1, "pool"),
new PaintingVariant(2, 1, "courbet"),
new PaintingVariant(2, 1, "sea"),
new PaintingVariant(2, 1, "sunset"),
new PaintingVariant(2, 1, "creebet"),
new PaintingVariant(1, 2, "wanderer"),
new PaintingVariant(1, 2, "graham"),
new PaintingVariant(2, 2, "match"),
new PaintingVariant(2, 2, "bust"),
new PaintingVariant(2, 2, "stage"),
new PaintingVariant(2, 2, "void"),
new PaintingVariant(2, 2, "skull_and_roses"),
new PaintingVariant(2, 2, "wither"),
new PaintingVariant(4, 2, "fighters"),
new PaintingVariant(4, 4, "pointer"),
new PaintingVariant(4, 4, "pigscene"),
new PaintingVariant(4, 4, "burning_skull"),
new PaintingVariant(4, 3, "skeleton"),
new PaintingVariant(2, 2, "earth"),
new PaintingVariant(2, 2, "wind"),
new PaintingVariant(2, 2, "water"),
new PaintingVariant(2, 2, "fire"),
new PaintingVariant(4, 3, "donkey_kong")
};
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.packet;
import com.viaversion.viaversion.api.protocol.packet.State;
public enum ClientboundConfigurationPackets1_21 implements ClientboundPacket1_21 {
COOKIE_REQUEST, // 0x00
CUSTOM_PAYLOAD, // 0x01
DISCONNECT, // 0x02
FINISH_CONFIGURATION, // 0x03
KEEP_ALIVE, // 0x04
PING, // 0x05
RESET_CHAT, // 0x06
REGISTRY_DATA, // 0x07
RESOURCE_PACK_POP, // 0x08
RESOURCE_PACK_PUSH, // 0x09
STORE_COOKIE, // 0x0A
TRANSFER, // 0x0B
UPDATE_ENABLED_FEATURES, // 0x0C
UPDATE_TAGS, // 0x0D
SELECT_KNOWN_PACKS, // 0x0E
CUSTOM_REPORT_DETAILS, // 0x0F
SERVER_LINKS; // 0x10
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
@Override
public State state() {
return State.CONFIGURATION;
}
}
@@ -0,0 +1,23 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.packet;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
public interface ClientboundPacket1_21 extends ClientboundPacketType {
}
@@ -0,0 +1,156 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.packet;
public enum ClientboundPackets1_21 implements ClientboundPacket1_21 {
BUNDLE_DELIMITER, // 0x00
ADD_ENTITY, // 0x01
ADD_EXPERIENCE_ORB, // 0x02
ANIMATE, // 0x03
AWARD_STATS, // 0x04
BLOCK_CHANGED_ACK, // 0x05
BLOCK_DESTRUCTION, // 0x06
BLOCK_ENTITY_DATA, // 0x07
BLOCK_EVENT, // 0x08
BLOCK_UPDATE, // 0x09
BOSS_EVENT, // 0x0A
CHANGE_DIFFICULTY, // 0x0B
CHUNK_BATCH_FINISHED, // 0x0C
CHUNK_BATCH_START, // 0x0D
CHUNKS_BIOMES, // 0x0E
CLEAR_TITLES, // 0x0F
COMMAND_SUGGESTIONS, // 0x10
COMMANDS, // 0x11
CONTAINER_CLOSE, // 0x12
CONTAINER_SET_CONTENT, // 0x13
CONTAINER_SET_DATA, // 0x14
CONTAINER_SET_SLOT, // 0x15
COOKIE_REQUEST, // 0x16
COOLDOWN, // 0x17
CUSTOM_CHAT_COMPLETIONS, // 0x18
CUSTOM_PAYLOAD, // 0x19
DAMAGE_EVENT, // 0x1A
DEBUG_SAMPLE, // 0x1B
DELETE_CHAT, // 0x1C
DISCONNECT, // 0x1D
DISGUISED_CHAT, // 0x1E
ENTITY_EVENT, // 0x1F
EXPLODE, // 0x20
FORGET_LEVEL_CHUNK, // 0x21
GAME_EVENT, // 0x22
HORSE_SCREEN_OPEN, // 0x23
HURT_ANIMATION, // 0x24
INITIALIZE_BORDER, // 0x25
KEEP_ALIVE, // 0x26
LEVEL_CHUNK_WITH_LIGHT, // 0x27
LEVEL_EVENT, // 0x28
LEVEL_PARTICLES, // 0x29
LIGHT_UPDATE, // 0x2A
LOGIN, // 0x2B
MAP_ITEM_DATA, // 0x2C
MERCHANT_OFFERS, // 0x2D
MOVE_ENTITY_POS, // 0x2E
MOVE_ENTITY_POS_ROT, // 0x2F
MOVE_ENTITY_ROT, // 0x30
MOVE_VEHICLE, // 0x31
OPEN_BOOK, // 0x32
OPEN_SCREEN, // 0x33
OPEN_SIGN_EDITOR, // 0x34
PING, // 0x35
PONG_RESPONSE, // 0x36
PLACE_GHOST_RECIPE, // 0x37
PLAYER_ABILITIES, // 0x38
PLAYER_CHAT, // 0x39
PLAYER_COMBAT_END, // 0x3A
PLAYER_COMBAT_ENTER, // 0x3B
PLAYER_COMBAT_KILL, // 0x3C
PLAYER_INFO_REMOVE, // 0x3D
PLAYER_INFO_UPDATE, // 0x3E
PLAYER_LOOK_AT, // 0x3F
PLAYER_POSITION, // 0x40
RECIPE, // 0x41
REMOVE_ENTITIES, // 0x42
REMOVE_MOB_EFFECT, // 0x43
RESET_SCORE, // 0x44
RESOURCE_PACK_POP, // 0x45
RESOURCE_PACK_PUSH, // 0x46
RESPAWN, // 0x47
ROTATE_HEAD, // 0x48
SECTION_BLOCKS_UPDATE, // 0x49
SELECT_ADVANCEMENTS_TAB, // 0x4A
SERVER_DATA, // 0x4B
SET_ACTION_BAR_TEXT, // 0x4C
SET_BORDER_CENTER, // 0x4D
SET_BORDER_LERP_SIZE, // 0x4E
SET_BORDER_SIZE, // 0x4F
SET_BORDER_WARNING_DELAY, // 0x50
SET_BORDER_WARNING_DISTANCE, // 0x51
SET_CAMERA, // 0x52
SET_CARRIED_ITEM, // 0x53
SET_CHUNK_CACHE_CENTER, // 0x54
SET_CHUNK_CACHE_RADIUS, // 0x55
SET_DEFAULT_SPAWN_POSITION, // 0x56
SET_DISPLAY_OBJECTIVE, // 0x57
SET_ENTITY_DATA, // 0x58
SET_ENTITY_LINK, // 0x59
SET_ENTITY_MOTION, // 0x5A
SET_EQUIPMENT, // 0x5B
SET_EXPERIENCE, // 0x5C
SET_HEALTH, // 0x5D
SET_OBJECTIVE, // 0x5E
SET_PASSENGERS, // 0x5F
SET_PLAYER_TEAM, // 0x60
SET_SCORE, // 0x61
SET_SIMULATION_DISTANCE, // 0x62
SET_SUBTITLE_TEXT, // 0x63
SET_TIME, // 0x64
SET_TITLE_TEXT, // 0x65
SET_TITLES_ANIMATION, // 0x66
SOUND_ENTITY, // 0x67
SOUND, // 0x68
START_CONFIGURATION, // 0x69
STOP_SOUND, // 0x6A
STORE_COOKIE, // 0x6B
SYSTEM_CHAT, // 0x6C
TAB_LIST, // 0x6D
TAG_QUERY, // 0x6E
TAKE_ITEM_ENTITY, // 0x6F
TELEPORT_ENTITY, // 0x70
TICKING_STATE, // 0x71
TICKING_STEP, // 0x72
TRANSFER, // 0x73
UPDATE_ADVANCEMENTS, // 0x74
UPDATE_ATTRIBUTES, // 0x75
UPDATE_MOB_EFFECT, // 0x76
UPDATE_RECIPES, // 0x77
UPDATE_TAGS, // 0x78
PROJECTILE_POWER, // 0x79
CUSTOM_REPORT_DETAILS, // 0x7A
SERVER_LINKS; // 0x7B
@Override
public int getId() {
return ordinal();
}
@Override
public String getName() {
return name();
}
}
@@ -0,0 +1,179 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.rewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
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.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.AttributeModifierMappings1_21;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import java.util.Arrays;
import java.util.List;
public final class BlockItemPacketRewriter1_21 extends StructuredItemRewriter<ClientboundPacket1_20_5, ServerboundPacket1_20_5, Protocol1_20_5To1_21> {
private static final List<String> DISCS = List.of("11", "13", "5", "blocks", "cat", "chirp", "far", "mall", "mellohi", "otherside", "pigstep", "relic", "stal", "strad", "wait", "ward");
public BlockItemPacketRewriter1_21(final Protocol1_20_5To1_21 protocol) {
super(protocol, Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY, Types1_21.ITEM, Types1_21.ITEM_ARRAY);
}
@Override
public void registerPackets() {
final BlockRewriter<ClientboundPacket1_20_5> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_20_5.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_20_5.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_20_5.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_20_5.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_20_5.BLOCK_ENTITY_DATA);
registerCooldown(ClientboundPackets1_20_5.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_20_5.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_20_5.SET_EQUIPMENT);
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerMerchantOffers1_20_5(ClientboundPackets1_20_5.MERCHANT_OFFERS, Types1_20_5.ITEM_COST, Types1_21.ITEM_COST, Types1_20_5.OPTIONAL_ITEM_COST, Types1_21.OPTIONAL_ITEM_COST);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
registerContainerSetData(ClientboundPackets1_20_5.CONTAINER_SET_DATA);
registerLevelParticles1_20_5(ClientboundPackets1_20_5.LEVEL_PARTICLES, Types1_20_5.PARTICLE, Types1_21.PARTICLE);
registerExplosion(ClientboundPackets1_20_5.EXPLODE, Types1_20_5.PARTICLE, Types1_21.PARTICLE); // Rewrites the included sound and particles
protocol.registerClientbound(ClientboundPackets1_20_5.HORSE_SCREEN_OPEN, wrapper -> {
wrapper.passthrough(Types.UNSIGNED_BYTE); // Container id
// Now written as columns
final int size = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT, Math.max(1, (size - 1) / 3));
});
protocol.registerClientbound(ClientboundPackets1_20_5.LEVEL_EVENT, wrapper -> {
final int id = wrapper.passthrough(Types.INT);
wrapper.passthrough(Types.BLOCK_POSITION1_14);
final int data = wrapper.read(Types.INT);
if (id == 1010) {
final int jukeboxSong = itemToJubeboxSong(data);
if (jukeboxSong == -1) {
wrapper.cancel();
return;
}
wrapper.write(Types.INT, jukeboxSong);
} else if (id == 2001) {
wrapper.write(Types.INT, protocol.getMappingData().getNewBlockStateId(data));
} else {
wrapper.write(Types.INT, data);
}
});
protocol.registerServerbound(ServerboundPackets1_20_5.USE_ITEM, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Hand
wrapper.passthrough(Types.VAR_INT); // Sequence
wrapper.read(Types.FLOAT); // Y rotation
wrapper.read(Types.FLOAT); // X rotation
});
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_20_5.UPDATE_RECIPES);
}
@Override
public Item handleItemToClient(final UserConnection connection, final Item item) {
if (item.isEmpty()) {
return item;
}
super.handleItemToClient(connection, item);
updateItemData(item);
return item;
}
public static void updateItemData(final Item item) {
final StructuredDataContainer dataContainer = item.dataContainer();
dataContainer.replaceKey(StructuredDataKey.FOOD1_20_5, StructuredDataKey.FOOD1_21);
dataContainer.replaceKey(StructuredDataKey.CONTAINER1_20_5, StructuredDataKey.CONTAINER1_21);
dataContainer.replaceKey(StructuredDataKey.CHARGED_PROJECTILES1_20_5, StructuredDataKey.CHARGED_PROJECTILES1_21);
dataContainer.replaceKey(StructuredDataKey.BUNDLE_CONTENTS1_20_5, StructuredDataKey.BUNDLE_CONTENTS1_21);
dataContainer.replace(StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21, attributeModifiers -> {
final AttributeModifiers1_21.AttributeModifier[] modifiers = Arrays.stream(attributeModifiers.modifiers()).map(modifier -> {
final AttributeModifiers1_20_5.ModifierData modData = modifier.modifier();
final AttributeModifiers1_21.ModifierData updatedModData = new AttributeModifiers1_21.ModifierData(Protocol1_20_5To1_21.mapAttributeUUID(modData.uuid(), modData.name()), modData.amount(), modData.operation());
return new AttributeModifiers1_21.AttributeModifier(modifier.attribute(), updatedModData, modifier.slotType());
}).toArray(AttributeModifiers1_21.AttributeModifier[]::new);
return new AttributeModifiers1_21(modifiers, attributeModifiers.showInTooltip());
});
}
@Override
public Item handleItemToServer(final UserConnection connection, final Item item) {
if (item.isEmpty()) {
return item;
}
super.handleItemToServer(connection, item);
downgradeItemData(item);
return item;
}
public static void downgradeItemData(final Item item) {
final StructuredDataContainer dataContainer = item.dataContainer();
dataContainer.replaceKey(StructuredDataKey.FOOD1_21, StructuredDataKey.FOOD1_20_5);
dataContainer.replaceKey(StructuredDataKey.CONTAINER1_21, StructuredDataKey.CONTAINER1_20_5);
dataContainer.replaceKey(StructuredDataKey.CHARGED_PROJECTILES1_21, StructuredDataKey.CHARGED_PROJECTILES1_20_5);
dataContainer.replaceKey(StructuredDataKey.BUNDLE_CONTENTS1_21, StructuredDataKey.BUNDLE_CONTENTS1_20_5);
dataContainer.remove(StructuredDataKey.JUKEBOX_PLAYABLE);
dataContainer.replace(StructuredDataKey.ATTRIBUTE_MODIFIERS1_21, StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5, attributeModifiers -> {
final AttributeModifiers1_20_5.AttributeModifier[] modifiers = Arrays.stream(attributeModifiers.modifiers()).map(modifier -> {
final AttributeModifiers1_21.ModifierData modData = modifier.modifier();
final String name = AttributeModifierMappings1_21.idToName(modData.id());
final AttributeModifiers1_20_5.ModifierData updatedModData = new AttributeModifiers1_20_5.ModifierData(
Protocol1_20_5To1_21.mapAttributeId(modData.id()),
name != null ? name : modData.id(),
modData.amount(),
modData.operation()
);
return new AttributeModifiers1_20_5.AttributeModifier(modifier.attribute(), updatedModData, modifier.slotType());
}).toArray(AttributeModifiers1_20_5.AttributeModifier[]::new);
return new AttributeModifiers1_20_5(modifiers, attributeModifiers.showInTooltip());
});
}
private int itemToJubeboxSong(final int id) {
String identifier = Protocol1_20_5To1_21.MAPPINGS.getFullItemMappings().identifier(id);
if (!identifier.contains("music_disc_")) {
return -1;
}
identifier = identifier.substring("minecraft:music_disc_".length());
return DISCS.indexOf(identifier);
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.util.SerializerVersion;
import com.viaversion.viaversion.util.TagUtil;
import com.viaversion.viaversion.util.UUIDUtil;
import java.util.UUID;
public final class ComponentRewriter1_21 extends ComponentRewriter<ClientboundPacket1_20_5> {
public ComponentRewriter1_21(final Protocol1_20_5To1_21 protocol) {
super(protocol, ReadType.NBT);
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag componentsTag) {
final CompoundTag attributeModifiers = TagUtil.getNamespacedCompoundTag(componentsTag, "minecraft:attribute_modifiers");
if (attributeModifiers != null) {
final ListTag<CompoundTag> modifiers = attributeModifiers.getListTag("modifiers", CompoundTag.class);
for (final CompoundTag modifier : modifiers) {
final String name = modifier.getString("name");
final UUID uuid = UUIDUtil.fromIntArray(modifier.getIntArrayTag("uuid").getValue());
final String id = Protocol1_20_5To1_21.mapAttributeUUID(uuid, name);
modifier.putString("id", id);
}
}
}
@Override
protected SerializerVersion inputSerializerVersion() {
return SerializerVersion.V1_20_5;
}
@Override
protected SerializerVersion outputSerializerVersion() {
return SerializerVersion.V1_20_5;
}
}
@@ -0,0 +1,159 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data.Enchantments1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.data.Paintings1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPacket1_20_5, Protocol1_20_5To1_21> {
public EntityPacketRewriter1_21(final Protocol1_20_5To1_21 protocol) {
super(protocol);
}
@Override
public void registerPackets() {
registerTrackerWithData1_19(ClientboundPackets1_20_5.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_20_5.SET_ENTITY_DATA, Types1_20_5.ENTITY_DATA_LIST, Types1_21.ENTITY_DATA_LIST);
registerRemoveEntities(ClientboundPackets1_20_5.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, wrapper -> {
final String type = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
final RegistryEntry[] entries = wrapper.passthrough(Types.REGISTRY_ENTRY_ARRAY);
if (type.equals("damage_type")) {
// Add required damage type
final CompoundTag campfireDamageType = new CompoundTag();
campfireDamageType.putString("scaling", "when_caused_by_living_non_player");
campfireDamageType.putString("message_id", "inFire");
campfireDamageType.putFloat("exhaustion", 0.1F);
wrapper.set(Types.REGISTRY_ENTRY_ARRAY, 0, addRegistryEntries(entries, new RegistryEntry("minecraft:campfire", campfireDamageType)));
} else {
handleRegistryData1_20_5(wrapper.user(), type, entries);
}
});
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.FINISH_CONFIGURATION, wrapper -> {
// Add new registries
final PacketWrapper paintingRegistryPacket = wrapper.create(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA);
paintingRegistryPacket.write(Types.STRING, "minecraft:painting_variant");
final RegistryEntry[] paintingsRegistry = new RegistryEntry[Paintings1_20_5.PAINTINGS.length];
for (int i = 0; i < Paintings1_20_5.PAINTINGS.length; i++) {
final PaintingVariant painting = Paintings1_20_5.PAINTINGS[i];
final CompoundTag tag = new CompoundTag();
tag.putInt("width", painting.width());
tag.putInt("height", painting.height());
tag.putString("asset_id", painting.assetId());
paintingsRegistry[i] = new RegistryEntry(painting.assetId(), tag);
}
paintingRegistryPacket.write(Types.REGISTRY_ENTRY_ARRAY, paintingsRegistry);
paintingRegistryPacket.send(Protocol1_20_5To1_21.class);
final PacketWrapper enchantmentRegistryPacket = wrapper.create(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA);
enchantmentRegistryPacket.write(Types.STRING, "minecraft:enchantment");
final RegistryEntry[] enchantmentRegistry = new RegistryEntry[Enchantments1_20_5.ENCHANTMENTS.size()];
for (int i = 0; i < Enchantments1_20_5.ENCHANTMENTS.size(); i++) {
final String key = Enchantments1_20_5.idToKey(i);
final CompoundTag tag = protocol.getMappingData().enchantment(i);
enchantmentRegistry[i] = new RegistryEntry(key, tag);
}
enchantmentRegistryPacket.write(Types.REGISTRY_ENTRY_ARRAY, enchantmentRegistry);
enchantmentRegistryPacket.send(Protocol1_20_5To1_21.class);
final PacketWrapper jukeboxSongsPacket = wrapper.create(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA);
jukeboxSongsPacket.write(Types.STRING, "minecraft:jukebox_song");
jukeboxSongsPacket.write(Types.REGISTRY_ENTRY_ARRAY, protocol.getMappingData().jukeboxSongs());
jukeboxSongsPacket.send(Protocol1_20_5To1_21.class);
});
protocol.registerClientbound(ClientboundPackets1_20_5.LOGIN, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // Entity id
map(Types.BOOLEAN); // Hardcore
map(Types.STRING_ARRAY); // World List
map(Types.VAR_INT); // Max players
map(Types.VAR_INT); // View distance
map(Types.VAR_INT); // Simulation distance
map(Types.BOOLEAN); // Reduced debug info
map(Types.BOOLEAN); // Show death screen
map(Types.BOOLEAN); // Limited crafting
map(Types.VAR_INT); // Dimension id
map(Types.STRING); // World
handler(worldDataTrackerHandlerByKey1_20_5(3));
handler(playerTrackerHandler());
handler(wrapper -> wrapper.user().get(EfficiencyAttributeStorage.class).onLoginSent(wrapper.user()));
}
});
protocol.registerClientbound(ClientboundPackets1_20_5.RESPAWN, wrapper -> {
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
});
}
@Override
protected void registerRewrites() {
filter().handler((event, data) -> {
final EntityDataType type = data.dataType();
if (type == Types1_20_5.ENTITY_DATA_TYPES.wolfVariantType) {
final int variant = data.value();
data.setTypeAndValue(Types1_21.ENTITY_DATA_TYPES.wolfVariantType, Holder.of(variant));
} else if (type == Types1_20_5.ENTITY_DATA_TYPES.paintingVariantType) {
final int variant = data.value();
data.setTypeAndValue(Types1_21.ENTITY_DATA_TYPES.paintingVariantType, Holder.of(variant));
} else {
data.setDataType(Types1_21.ENTITY_DATA_TYPES.byId(type.typeId()));
}
});
registerEntityDataTypeHandler(
Types1_21.ENTITY_DATA_TYPES.itemType,
Types1_21.ENTITY_DATA_TYPES.blockStateType,
Types1_21.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_21.ENTITY_DATA_TYPES.particleType,
Types1_21.ENTITY_DATA_TYPES.particlesType,
Types1_21.ENTITY_DATA_TYPES.componentType,
Types1_21.ENTITY_DATA_TYPES.optionalComponentType
);
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
}
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_20_5.getTypeFromId(type);
}
}
@@ -0,0 +1,79 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 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_20_5to1_21.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
public final class EfficiencyAttributeStorage implements StorableObject {
private static final int MINING_EFFICIENCY_ID = 19;
private final Object lock = new Object(); // Slightly sloppy locking, but should be good enough
private volatile boolean loginSent;
private volatile StoredEfficiency efficiencyLevel;
public void setEfficiencyLevel(final StoredEfficiency efficiencyLevel, final UserConnection connection) {
this.efficiencyLevel = efficiencyLevel;
sendAttributesPacket(connection);
}
public void onLoginSent(final UserConnection connection) {
this.loginSent = true;
sendAttributesPacket(connection);
}
private void sendAttributesPacket(final UserConnection connection) {
final StoredEfficiency efficiency;
synchronized (lock) {
// Older servers (and often Bungee) will send world state packets before sending the login packet
if (!loginSent || efficiencyLevel == null) {
return;
}
efficiency = efficiencyLevel;
efficiencyLevel = null;
}
final PacketWrapper attributesPacket = PacketWrapper.create(ClientboundPackets1_21.UPDATE_ATTRIBUTES, connection);
attributesPacket.write(Types.VAR_INT, efficiency.entityId());
attributesPacket.write(Types.VAR_INT, 1); // Size
attributesPacket.write(Types.VAR_INT, MINING_EFFICIENCY_ID); // Attribute ID
attributesPacket.write(Types.DOUBLE, 0D); // Base
final int level = efficiency.level;
if (level > 0) {
final double modifierAmount = (level * level) + 1D;
attributesPacket.write(Types.VAR_INT, 1); // Modifiers
attributesPacket.write(Types.STRING, "minecraft:enchantment.efficiency/mainhand"); // Id
attributesPacket.write(Types.DOUBLE, modifierAmount);
attributesPacket.write(Types.BYTE, (byte) 0); // 'Add' operation
} else {
attributesPacket.write(Types.VAR_INT, 0); // Modifiers
}
attributesPacket.scheduleSend(Protocol1_20_5To1_21.class);
}
public record StoredEfficiency(int entityId, int level) {
}
}
@@ -18,10 +18,8 @@
package com.viaversion.viaversion.protocols.v1_8to1_9;
import com.google.gson.JsonElement;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -68,10 +66,6 @@ public class Protocol1_8To1_9 extends AbstractProtocol<ClientboundPackets1_8, Cl
super(ClientboundPackets1_8.class, ClientboundPackets1_9.class, ServerboundPackets1_8.class, ServerboundPackets1_9.class);
}
public static Item getHandItem(final UserConnection info) {
return Via.getManager().getProviders().get(HandItemProvider.class).getHandItem(info);
}
public static boolean isSword(int id) {
return switch (id) {
case 267, // Iron sword
@@ -18,12 +18,13 @@
package com.viaversion.viaversion.protocols.v1_8to1_9.provider;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.platform.providers.Provider;
import org.checkerframework.checker.nullness.qual.Nullable;
public class HandItemProvider implements Provider {
public Item getHandItem(final UserConnection info) {
return new DataItem(0, (byte) 0, (short) 0, null);
public @Nullable Item getHandItem(final UserConnection connection) {
return null;
}
}
@@ -43,7 +43,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class ItemPacketRewriter1_9 extends ItemRewriter<ClientboundPackets1_8, ServerboundPackets1_9, Protocol1_8To1_9> {
public ItemPacketRewriter1_9(final Protocol1_8To1_9 protocol) {
super(protocol, null, null);
super(protocol, Types.ITEM1_8, Types.ITEM1_8_SHORT_ARRAY);
}
@Override
@@ -40,7 +40,6 @@ import com.viaversion.viaversion.protocols.v1_8to1_9.storage.ClientChunks;
import com.viaversion.viaversion.protocols.v1_8to1_9.storage.EntityTracker1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.storage.MovementTracker;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.SerializerVersion;
public class PlayerPacketRewriter1_9 {
public static void register(Protocol1_8To1_9 protocol) {
@@ -276,33 +275,11 @@ public class PlayerPacketRewriter1_9 {
public void register() {
map(Types.STRING); // 0 - Channel Name
handlerSoftFail(wrapper -> {
String name = wrapper.get(Types.STRING, 0);
final String name = wrapper.get(Types.STRING, 0);
if (name.equals("MC|BOpen")) {
wrapper.write(Types.VAR_INT, 0);
} else if (name.equals("MC|TrList")) {
wrapper.passthrough(Types.INT); // ID
Short size = wrapper.passthrough(Types.UNSIGNED_BYTE);
for (int i = 0; i < size; ++i) {
Item item1 = wrapper.passthrough(Types.ITEM1_8);
protocol.getItemRewriter().handleItemToClient(wrapper.user(), item1);
Item item2 = wrapper.passthrough(Types.ITEM1_8);
protocol.getItemRewriter().handleItemToClient(wrapper.user(), item2);
boolean present = wrapper.passthrough(Types.BOOLEAN);
if (present) {
Item item3 = wrapper.passthrough(Types.ITEM1_8);
protocol.getItemRewriter().handleItemToClient(wrapper.user(), item3);
}
wrapper.passthrough(Types.BOOLEAN);
wrapper.passthrough(Types.INT);
wrapper.passthrough(Types.INT);
}
protocol.getItemRewriter().handleTradeList(wrapper);
}
});
}
@@ -432,7 +409,7 @@ public class PlayerPacketRewriter1_9 {
final StringTag pageTag = pages.get(i);
final String value = pageTag.getValue();
pageTag.setValue(ComponentUtil.convertJson(value, SerializerVersion.V1_9, SerializerVersion.V1_8).toString());
pageTag.setValue(ComponentUtil.plainToJson(value).toString());
}
}
}
@@ -44,6 +44,7 @@ import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_8;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ServerboundPackets1_9;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.CommandBlockProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.HandItemProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.storage.ClientChunks;
import com.viaversion.viaversion.protocols.v1_8to1_9.storage.EntityTracker1_9;
import com.viaversion.viaversion.util.ComponentUtil;
@@ -293,7 +294,7 @@ public class WorldPacketRewriter1_9 {
wrapper.write(Types.BLOCK_POSITION1_8, new BlockPosition(-1, -1, -1));
wrapper.write(Types.UNSIGNED_BYTE, (short) 255);
// Write item in hand
Item item = Protocol1_8To1_9.getHandItem(wrapper.user());
Item item = Via.getManager().getProviders().get(HandItemProvider.class).getHandItem(wrapper.user());
// Blocking patch
if (Via.getConfig().isShieldBlocking()) {
EntityTracker1_9 tracker = wrapper.user().getEntityTracker(Protocol1_8To1_9.class);
@@ -350,7 +351,7 @@ public class WorldPacketRewriter1_9 {
if (hand != 0) wrapper.cancel();
});
handler(wrapper -> {
Item item = Protocol1_8To1_9.getHandItem(wrapper.user());
Item item = Via.getManager().getProviders().get(HandItemProvider.class).getHandItem(wrapper.user());
wrapper.write(Types.ITEM1_8, item); // 3 - Item
});
map(Types.UNSIGNED_BYTE); // 4 - X
@@ -28,7 +28,7 @@ import com.viaversion.viaversion.rewriter.ItemRewriter;
public class ItemPacketRewriter1_10 extends ItemRewriter<ClientboundPackets1_9_3, ServerboundPackets1_9_3, Protocol1_9_3To1_10> {
public ItemPacketRewriter1_10(Protocol1_9_3To1_10 protocol) {
super(protocol, Types.ITEM1_8, null);
super(protocol, Types.ITEM1_8, Types.ITEM1_8_SHORT_ARRAY);
}
@Override
@@ -28,23 +28,41 @@ public class AttributeRewriter<C extends ClientboundPacketType> {
this.protocol = protocol;
}
public void register1_20_5(C packetType) {
public void register1_21(C packetType) {
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
final int size = wrapper.passthrough(Types.VAR_INT);
int newSize = size;
for (int i = 0; i < size; i++) {
final int attributeId = wrapper.read(Types.VAR_INT);
wrapper.write(Types.VAR_INT, protocol.getMappingData().getNewAttributeId(attributeId));
final int mappedId = protocol.getMappingData().getNewAttributeId(attributeId);
if (mappedId == -1) {
newSize--;
wrapper.read(Types.DOUBLE); // Base
final int modifierSize = wrapper.read(Types.VAR_INT);
for (int j = 0; j < modifierSize; j++) {
wrapper.read(Types.STRING); // ID
wrapper.read(Types.DOUBLE); // Amount
wrapper.read(Types.BYTE); // Operation
}
continue;
}
wrapper.write(Types.VAR_INT, mappedId);
wrapper.passthrough(Types.DOUBLE); // Base
final int modifierSize = wrapper.passthrough(Types.VAR_INT);
for (int j = 0; j < modifierSize; j++) {
wrapper.passthrough(Types.UUID); // ID
wrapper.passthrough(Types.STRING); // ID
wrapper.passthrough(Types.DOUBLE); // Amount
wrapper.passthrough(Types.BYTE); // Operation
}
}
if (size != newSize) {
wrapper.set(Types.VAR_INT, 1, newSize);
}
});
}
}
@@ -20,6 +20,7 @@ package com.viaversion.viaversion.rewriter;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
@@ -154,25 +155,26 @@ public class BlockRewriter<C extends ClientboundPacketType> {
}
public void registerLevelEvent(C packetType, int playRecordId, int blockBreakId) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
public void register() {
map(Types.INT); // Effect Id
map(positionType); // Location
map(Types.INT); // Data
handler(wrapper -> {
int id = wrapper.get(Types.INT, 0);
int data = wrapper.get(Types.INT, 1);
if (id == playRecordId && protocol.getMappingData().getItemMappings() != null) {
wrapper.set(Types.INT, 1, protocol.getMappingData().getNewItemId(data));
} else if (id == blockBreakId && protocol.getMappingData().getBlockStateMappings() != null) {
wrapper.set(Types.INT, 1, protocol.getMappingData().getNewBlockStateId(data));
}
});
protocol.registerClientbound(packetType, wrapper -> {
final int id = wrapper.passthrough(Types.INT);
wrapper.passthrough(positionType);
final int data = wrapper.read(Types.INT);
final MappingData mappingData = protocol.getMappingData();
if (playRecordId != -1 && id == playRecordId && mappingData.getItemMappings() != null) {
wrapper.write(Types.INT, mappingData.getNewItemId(data));
} else if (id == blockBreakId && mappingData.getBlockStateMappings() != null) {
wrapper.write(Types.INT, mappingData.getNewBlockStateId(data));
} else {
wrapper.write(Types.INT, data);
}
});
}
public void registerLevelEvent1_21(C packetType, int blockBreakId) {
registerLevelEvent(packetType, -1, blockBreakId);
}
public void registerLevelChunk(C packetType, Type<Chunk> chunkType, Type<Chunk> newChunkType) {
registerLevelChunk(packetType, chunkType, newChunkType, null);
}
@@ -36,13 +36,15 @@ import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.SerializerVersion;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Handles json chat components, containing methods to override certain parts of the handling.
* Handles json and tag components, containing methods to override certain parts of the handling.
* Also contains methods to register a few of the packets using components.
*/
public class ComponentRewriter<C extends ClientboundPacketType> {
public class ComponentRewriter<C extends ClientboundPacketType> implements com.viaversion.viaversion.api.rewriter.ComponentRewriter {
protected final Protocol<C, ?, ?, ?> protocol;
protected final ReadType type;
@@ -249,6 +251,7 @@ public class ComponentRewriter<C extends ClientboundPacketType> {
// -----------------------------------------------------------------------
// Tag methods
@Override
public void processTag(final UserConnection connection, @Nullable final Tag tag) {
if (tag == null) {
return;
@@ -309,6 +312,48 @@ public class ComponentRewriter<C extends ClientboundPacketType> {
if (contents != null) {
processTag(connection, contents.get("name"));
}
} else if (action.equals("show_item")) {
convertLegacyContents(hoverEventTag);
final CompoundTag contentsTag = hoverEventTag.getCompoundTag("contents");
if (contentsTag == null) {
return;
}
final CompoundTag componentsTag = contentsTag.getCompoundTag("components");
if (componentsTag != null) {
handleShowItem(connection, componentsTag);
}
}
}
protected void handleShowItem(final UserConnection connection, final CompoundTag componentsTag) {
// To override if needed
}
protected SerializerVersion inputSerializerVersion() {
return null;
}
protected SerializerVersion outputSerializerVersion() {
return null;
}
private void convertLegacyContents(final CompoundTag hoverEvent) {
if (inputSerializerVersion() == null || outputSerializerVersion() == null) {
return;
}
final Tag valueTag = hoverEvent.remove("value");
if (valueTag != null) {
final CompoundTag tag = ComponentUtil.deserializeShowItem(valueTag, inputSerializerVersion());
final CompoundTag contentsTag = new CompoundTag();
contentsTag.put("id", tag.getStringTag("id"));
contentsTag.put("count", tag.getIntTag("count"));
if (tag.get("tag") instanceof CompoundTag) {
contentsTag.putString("tag", outputSerializerVersion().toSNBT(tag.getCompoundTag("tag")));
}
hoverEvent.put("contents", contentsTag);
}
}
@@ -21,6 +21,7 @@ import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.Int2IntMapMappings;
@@ -32,9 +33,9 @@ import com.viaversion.viaversion.api.data.entity.TrackedEntity;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -51,6 +52,7 @@ import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandlerEventImpl;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.TagUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@@ -190,6 +192,10 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
registerEntityDataTypeHandler(itemType, null, blockStateType, particleType, null);
}
public void registerEntityDataTypeHandler(@Nullable EntityDataType itemType, @Nullable EntityDataType blockStateType, @Nullable EntityDataType optionalBlockStateType, @Nullable EntityDataType particleType, @Nullable EntityDataType particlesType) {
registerEntityDataTypeHandler(itemType, blockStateType, optionalBlockStateType, particleType, particlesType, null, null);
}
/**
* Registers an entity data handler to rewrite, item, block, and particle ids stored in entity data.
*
@@ -198,8 +204,12 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
* @param optionalBlockStateType optional block state data type if needed
* @param particleType particle data type if needed
* @param particlesType particles data type if needed
* @param componentType component data type if needed
* @param optionalComponentType optional component data type if needed
*/
public void registerEntityDataTypeHandler(@Nullable EntityDataType itemType, @Nullable EntityDataType blockStateType, @Nullable EntityDataType optionalBlockStateType, @Nullable EntityDataType particleType, @Nullable EntityDataType particlesType) {
public void registerEntityDataTypeHandler(@Nullable EntityDataType itemType, @Nullable EntityDataType blockStateType, @Nullable EntityDataType optionalBlockStateType,
@Nullable EntityDataType particleType, @Nullable EntityDataType particlesType,
@Nullable EntityDataType componentType, @Nullable EntityDataType optionalComponentType) {
filter().handler((event, data) -> {
final EntityDataType type = data.dataType();
if (type == itemType) {
@@ -219,6 +229,9 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
for (final Particle particle : particles) {
rewriteParticle(event.user(), particle);
}
} else if (type == componentType || type == optionalComponentType) {
final Tag component = data.value();
protocol.getComponentRewriter().processTag(event.user(), component);
}
});
}
@@ -445,27 +458,32 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
public PacketHandler worldDataTrackerHandlerByKey1_20_5(final int dimensionIdIndex) {
return wrapper -> {
EntityTracker tracker = tracker(wrapper.user());
int dimensionId = wrapper.get(Types.VAR_INT, dimensionIdIndex);
DimensionData dimensionData = tracker.dimensionData(dimensionId);
if (dimensionData == null) {
protocol.getLogger().severe("Dimension data missing for dimension: " + dimensionId + ", falling back to overworld");
dimensionData = tracker.dimensionData("minecraft:overworld");
Preconditions.checkNotNull(dimensionData, "Overworld data missing");
}
tracker.setCurrentWorldSectionHeight(dimensionData.height() >> 4);
tracker.setCurrentMinY(dimensionData.minY());
String world = wrapper.get(Types.STRING, 0);
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
tracker.clearEntities();
tracker.trackClientEntity();
}
tracker.setCurrentWorld(world);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
};
}
public void trackWorldDataByKey1_20_5(final UserConnection connection, final int dimensionId, final String world) {
// Track world height for use in chunk data
EntityTracker tracker = tracker(connection);
DimensionData dimensionData = tracker.dimensionData(dimensionId);
if (dimensionData == null) {
protocol.getLogger().severe("Dimension data missing for dimension: " + dimensionId + ", falling back to overworld");
dimensionData = tracker.dimensionData("overworld");
Preconditions.checkNotNull(dimensionData, "Overworld data missing");
}
tracker.setCurrentWorldSectionHeight(dimensionData.height() >> 4);
tracker.setCurrentMinY(dimensionData.minY());
// Clear entities if the world changes
if (tracker.currentWorld() != null && !tracker.currentWorld().equals(world)) {
tracker.clearEntities();
tracker.trackClientEntity();
}
tracker.setCurrentWorld(world);
}
public PacketHandler biomeSizeTracker() {
return wrapper -> trackBiomeSize(wrapper.user(), wrapper.get(Types.NAMED_COMPOUND_TAG, 0));
}
@@ -502,22 +520,17 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
tracker(connection).setDimensions(dimensionDataMap);
}
public PacketHandler registryDataHandler1_20_5() {
return wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.get(Types.STRING, 0));
if (registryKey.equals("worldgen/biome")) {
final RegistryEntry[] entries = wrapper.get(Types.REGISTRY_ENTRY_ARRAY, 0);
tracker(wrapper.user()).setBiomesSent(entries.length);
} else if (registryKey.equals("dimension_type")) {
final RegistryEntry[] entries = wrapper.get(Types.REGISTRY_ENTRY_ARRAY, 0);
final Map<String, DimensionData> dimensionDataMap = new HashMap<>(entries.length);
for (int i = 0; i < entries.length; i++) {
final RegistryEntry entry = entries[i];
dimensionDataMap.put(Key.stripMinecraftNamespace(entry.key()), new DimensionDataImpl(i, (CompoundTag) entry.tag()));
}
tracker(wrapper.user()).setDimensions(dimensionDataMap);
public void handleRegistryData1_20_5(final UserConnection connection, final String registryKey, final RegistryEntry[] entries) {
if (registryKey.equals("worldgen/biome")) {
tracker(connection).setBiomesSent(entries.length);
} else if (registryKey.equals("dimension_type")) {
final Map<String, DimensionData> dimensionDataMap = new HashMap<>(entries.length);
for (int i = 0; i < entries.length; i++) {
final RegistryEntry entry = entries[i];
dimensionDataMap.put(Key.stripMinecraftNamespace(entry.key()), new DimensionDataImpl(i, (CompoundTag) entry.tag()));
}
};
tracker(connection).setDimensions(dimensionDataMap);
}
}
// ---------------------------------------------------------------------------
@@ -579,6 +592,13 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
// ---------------------------------------------------------------------------
public RegistryEntry[] addRegistryEntries(final RegistryEntry[] entries, final RegistryEntry... toAdd) {
final int length = entries.length;
final RegistryEntry[] newEntries = Arrays.copyOf(entries, length + toAdd.length);
System.arraycopy(toAdd, 0, newEntries, length, toAdd.length);
return newEntries;
}
public void rewriteParticle(UserConnection connection, Particle particle) {
ParticleMappings mappings = protocol.getMappingData().getParticleMappings();
int id = particle.id();
@@ -17,6 +17,7 @@
*/
package com.viaversion.viaversion.rewriter;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.Mappings;
import com.viaversion.viaversion.api.data.ParticleMappings;
@@ -28,6 +29,7 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
import com.viaversion.viaversion.api.rewriter.RewriterBase;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
@@ -234,6 +236,41 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
});
}
public void registerCustomPayloadTradeList(C packetType) {
protocol.registerClientbound(packetType, new PacketHandlers() {
@Override
protected void register() {
map(Types.STRING); // 0 - Channel
handlerSoftFail(wrapper -> {
final String channel = wrapper.get(Types.STRING, 0);
if (channel.equals("MC|TrList")) {
handleTradeList(wrapper);
}
});
}
});
}
public void handleTradeList(final PacketWrapper wrapper) {
wrapper.passthrough(Types.INT); // Window ID
final int size = wrapper.passthrough(Types.UNSIGNED_BYTE);
for (int i = 0; i < size; i++) {
handleClientboundItem(wrapper); // Input Item
handleClientboundItem(wrapper); // Output Item
if (wrapper.passthrough(Types.BOOLEAN)) {
handleClientboundItem(wrapper); // Second Item
}
wrapper.passthrough(Types.BOOLEAN); // Trade disabled
wrapper.passthrough(Types.INT); // Number of tools uses
wrapper.passthrough(Types.INT); // Maximum number of trade uses
}
}
// 1.14.4+
public void registerMerchantOffers(C packetType) {
protocol.registerClientbound(packetType, wrapper -> {
@@ -346,15 +383,7 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
});
}
public void registerAdvancements1_20_2(C packetType) {
registerAdvancements1_20_2(packetType, Types.COMPONENT);
}
public void registerAdvancements1_20_3(C packetType) {
registerAdvancements1_20_2(packetType, Types.TAG);
}
private void registerAdvancements1_20_2(C packetType, Type<?> componentType) {
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.BOOLEAN); // Reset/clear
int size = wrapper.passthrough(Types.VAR_INT); // Mapping size
@@ -364,8 +393,14 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
// Display data
if (wrapper.passthrough(Types.BOOLEAN)) {
wrapper.passthrough(componentType); // Title
wrapper.passthrough(componentType); // Description
final Tag title = wrapper.passthrough(Types.TAG);
final Tag description = wrapper.passthrough(Types.TAG);
final ComponentRewriter componentRewriter = protocol.getComponentRewriter();
if (componentRewriter != null) {
componentRewriter.processTag(wrapper.user(), title);
componentRewriter.processTag(wrapper.user(), description);
}
handleClientboundItem(wrapper); // Icon
wrapper.passthrough(Types.VAR_INT); // Frame type
int flags = wrapper.passthrough(Types.INT); // Flags
@@ -469,7 +504,7 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
}
public void registerExplosion(C packetType, Type<Particle> unmappedParticleType, Type<Particle> mappedParticleType) {
final SoundRewriter<C> cSoundRewriter = new SoundRewriter<>(protocol);
final SoundRewriter<C> soundRewriter = new SoundRewriter<>(protocol);
protocol.registerClientbound(packetType, wrapper -> {
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
@@ -493,7 +528,7 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
rewriteParticle(wrapper.user(), smallExplosionParticle);
rewriteParticle(wrapper.user(), largeExplosionParticle);
cSoundRewriter.soundHolderHandler().handle(wrapper);
soundRewriter.soundHolderHandler().handle(wrapper);
});
}
@@ -56,7 +56,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
}
public void handleRecipeType(PacketWrapper wrapper, String type) {
RecipeConsumer handler = recipeHandlers.get(type);
RecipeConsumer handler = recipeHandlers.get(Key.stripMinecraftNamespace(type));
if (handler != null) {
handler.accept(wrapper);
}
@@ -73,7 +73,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
for (int i = 0; i < size; i++) {
String type = wrapper.passthrough(Types.STRING);
wrapper.passthrough(Types.STRING); // Recipe Identifier
handleRecipeType(wrapper, Key.stripMinecraftNamespace(type));
handleRecipeType(wrapper, type);
}
});
}
@@ -82,7 +82,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
protocol.registerClientbound(packetType, wrapper -> {
int size = wrapper.passthrough(Types.VAR_INT);
for (int i = 0; i < size; i++) {
wrapper.passthrough(Types.STRING);// Recipe Identifier
wrapper.passthrough(Types.STRING); // Recipe Identifier
final int typeId = wrapper.passthrough(Types.VAR_INT);
final String type = protocol.getMappingData().getRecipeSerializerMappings().identifier(typeId);
@@ -17,13 +17,23 @@
*/
package com.viaversion.viaversion.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.data.MappingData;
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.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
import com.viaversion.viaversion.api.type.Type;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public class StructuredItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
T extends Protocol<C, ?, ?, S>> extends ItemRewriter<C, S, T> {
@@ -43,14 +53,46 @@ public class StructuredItemRewriter<C extends ClientboundPacketType, S extends S
}
final MappingData mappingData = protocol.getMappingData();
final StructuredDataContainer dataContainer = item.dataContainer();
if (mappingData != null) {
if (mappingData.getItemMappings() != null) {
item.setIdentifier(mappingData.getNewItemId(item.identifier()));
}
if (mappingData.getDataComponentSerializerMappings() != null) {
item.dataContainer().setIdLookup(protocol, true);
final FullMappings dataComponentMappings = mappingData.getDataComponentSerializerMappings();
if (dataComponentMappings != null) {
dataContainer.setIdLookup(protocol, true);
dataContainer.updateIds(protocol, dataComponentMappings::getNewId);
}
}
final ComponentRewriter componentRewriter = protocol.getComponentRewriter();
if (componentRewriter != null) {
// Handle name and lore components
final StructuredData<Tag> customNameData = dataContainer.getNonEmpty(StructuredDataKey.CUSTOM_NAME);
if (customNameData != null) {
final Tag originalName = customNameData.value().copy();
componentRewriter.processTag(connection, customNameData.value());
if (!customNameData.value().equals(originalName)) {
saveTag(createCustomTag(item), originalName, "Name");
}
}
final StructuredData<Tag[]> loreData = dataContainer.getNonEmpty(StructuredDataKey.LORE);
if (loreData != null) {
for (final Tag tag : loreData.value()) {
componentRewriter.processTag(connection, tag);
}
}
}
Int2IntFunction itemIdRewriter = null;
Int2IntFunction blockIdRewriter = null;
if (mappingData != null) {
itemIdRewriter = mappingData.getItemMappings() != null ? mappingData::getNewItemId : null;
blockIdRewriter = mappingData.getBlockMappings() != null ? mappingData::getNewBlockId : null;
}
updateItemComponents(connection, dataContainer, this::handleItemToClient, itemIdRewriter, blockIdRewriter);
return item;
}
@@ -61,14 +103,111 @@ public class StructuredItemRewriter<C extends ClientboundPacketType, S extends S
}
final MappingData mappingData = protocol.getMappingData();
final StructuredDataContainer dataContainer = item.dataContainer();
if (mappingData != null) {
if (mappingData.getItemMappings() != null) {
item.setIdentifier(mappingData.getOldItemId(item.identifier()));
}
if (mappingData.getDataComponentSerializerMappings() != null) {
item.dataContainer().setIdLookup(protocol, false);
final FullMappings dataComponentMappings = mappingData.getDataComponentSerializerMappings();
if (dataComponentMappings != null) {
dataContainer.setIdLookup(protocol, false);
dataContainer.updateIds(protocol, id -> dataComponentMappings.inverse().getNewId(id));
}
}
restoreTextComponents(item);
Int2IntFunction itemIdRewriter = null;
Int2IntFunction blockIdRewriter = null;
if (mappingData != null) {
itemIdRewriter = mappingData.getItemMappings() != null ? mappingData::getOldItemId : null;
blockIdRewriter = mappingData.getBlockMappings() != null ? mappingData::getOldBlockId : null;
}
updateItemComponents(connection, dataContainer, this::handleItemToServer, itemIdRewriter, blockIdRewriter);
return item;
}
protected void updateItemComponents(UserConnection connection, StructuredDataContainer container, ItemHandler itemHandler, @Nullable Int2IntFunction idRewriter, @Nullable Int2IntFunction blockIdRewriter) {
// Specific types that need deep handling
if (idRewriter != null) {
container.updateIfPresent(StructuredDataKey.TRIM, value -> value.rewrite(idRewriter));
container.updateIfPresent(StructuredDataKey.POT_DECORATIONS, value -> value.rewrite(idRewriter));
}
if (blockIdRewriter != null) {
container.updateIfPresent(StructuredDataKey.TOOL, value -> value.rewrite(blockIdRewriter));
container.updateIfPresent(StructuredDataKey.CAN_PLACE_ON, value -> value.rewrite(blockIdRewriter));
container.updateIfPresent(StructuredDataKey.CAN_BREAK, value -> value.rewrite(blockIdRewriter));
}
// Look for item types
for (final Map.Entry<StructuredDataKey<?>, StructuredData<?>> entry : container.data().entrySet()) {
final StructuredData<?> data = entry.getValue();
if (data.isEmpty()) {
continue;
}
final StructuredDataKey<?> key = entry.getKey();
final Class<?> outputClass = key.type().getOutputClass();
if (outputClass == Item.class) {
//noinspection unchecked
final StructuredData<Item> itemData = (StructuredData<Item>) data;
itemData.setValue(itemHandler.rewrite(connection, itemData.value()));
} else if (outputClass == Item[].class) {
//noinspection unchecked
final StructuredData<Item[]> itemArrayData = (StructuredData<Item[]>) data;
final Item[] items = itemArrayData.value();
for (int i = 0; i < items.length; i++) {
items[i] = itemHandler.rewrite(connection, items[i]);
}
}
}
}
protected void restoreTextComponents(final Item item) {
final StructuredDataContainer data = item.dataContainer();
final StructuredData<CompoundTag> customData = data.getNonEmpty(StructuredDataKey.CUSTOM_DATA);
if (customData == null) {
return;
}
// Remove custom name
if (customData.value().remove(nbtTagName("customName")) != null) {
data.remove(StructuredDataKey.CUSTOM_NAME);
} else {
final Tag name = removeBackupTag(customData.value(), "Name");
if (name != null) {
data.set(StructuredDataKey.CUSTOM_NAME, name);
}
}
}
protected CompoundTag createCustomTag(final Item item) {
final StructuredDataContainer data = item.dataContainer();
final StructuredData<CompoundTag> customData = data.getNonEmpty(StructuredDataKey.CUSTOM_DATA);
if (customData != null) {
return customData.value();
}
final CompoundTag tag = new CompoundTag();
data.set(StructuredDataKey.CUSTOM_DATA, tag);
return tag;
}
protected void saveTag(final CompoundTag customData, final Tag tag, final String name) {
final String backupName = nbtTagName(name);
if (!customData.contains(backupName)) {
customData.put(backupName, tag);
}
}
protected @Nullable Tag removeBackupTag(final CompoundTag customData, final String tagName) {
return customData.remove(nbtTagName(tagName));
}
@FunctionalInterface
public interface ItemHandler {
Item rewrite(UserConnection connection, Item item);
}
}
@@ -40,11 +40,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class TagRewriter<C extends ClientboundPacketType> implements com.viaversion.viaversion.api.rewriter.TagRewriter {
private static final int[] EMPTY_ARRAY = {};
private final Protocol<C, ?, ?, ?> protocol;
private final Map<RegistryType, List<TagData>> newTags = new EnumMap<>(RegistryType.class);
private final Map<RegistryType, List<TagData>> toAdd = new EnumMap<>(RegistryType.class);
private final Map<RegistryType, Map<String, String>> toRename = new EnumMap<>(RegistryType.class);
private final Map<RegistryType, Set<String>> toRemove = new EnumMap<>(RegistryType.class);
private final Set<String> toRemoveRegistries = new HashSet<>();
private final Protocol<C, ?, ?, ?> protocol;
public TagRewriter(final Protocol<C, ?, ?, ?> protocol) {
this.protocol = protocol;
@@ -56,6 +56,7 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
return;
}
// TODO Tags for player synchronized registries
for (RegistryType type : RegistryType.getValues()) {
List<TagData> tags = protocol.getMappingData().getTags(type);
if (tags != null) {
@@ -174,8 +175,9 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
}
public void handle(PacketWrapper wrapper, @Nullable IdRewriteFunction rewriteFunction, @Nullable List<TagData> newTags, @Nullable Map<String, String> tagsToRename, @Nullable Set<String> tagsToRemove) {
int tagsSize = wrapper.read(Types.VAR_INT);
final int tagsSize = wrapper.read(Types.VAR_INT);
final List<TagData> tags = new ArrayList<>(newTags != null ? tagsSize + newTags.size() : tagsSize);
final Set<String> currentTags = new HashSet<>(tagsSize);
for (int i = 0; i < tagsSize; i++) {
String key = wrapper.read(Types.STRING);
@@ -201,6 +203,7 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
}
tags.add(new TagData(key, ids));
currentTags.add(Key.stripMinecraftNamespace(key));
}
if (tagsToRemove != null) {
@@ -209,7 +212,11 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
// Add new tags if present
if (newTags != null) {
tags.addAll(newTags);
for (final TagData tag : newTags) {
if (!currentTags.contains(Key.stripMinecraftNamespace(tag.identifier()))) {
tags.add(tag);
}
}
}
// Write the tags
@@ -235,12 +242,12 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
@Override
public @Nullable List<TagData> getNewTags(RegistryType tagType) {
return newTags.get(tagType);
return toAdd.get(tagType);
}
@Override
public List<TagData> getOrComputeNewTags(RegistryType tagType) {
return newTags.computeIfAbsent(tagType, type -> new ArrayList<>());
return toAdd.computeIfAbsent(tagType, type -> new ArrayList<>());
}
public @Nullable IdRewriteFunction getRewriter(RegistryType tagType) {
@@ -249,6 +256,7 @@ public class TagRewriter<C extends ClientboundPacketType> implements com.viavers
case BLOCK -> mappingData != null && mappingData.getBlockMappings() != null ? mappingData::getNewBlockId : null;
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;
};
}
@@ -30,12 +30,9 @@ public final class TagUtil {
}
public static ListTag<CompoundTag> getRegistryEntries(final CompoundTag tag, final String key, final @Nullable ListTag<CompoundTag> defaultValue) {
CompoundTag registry = tag.getCompoundTag(Key.namespaced(key));
CompoundTag registry = getNamespacedCompoundTag(tag, key);
if (registry == null) {
registry = tag.getCompoundTag(Key.stripMinecraftNamespace(key));
if (registry == null) {
return defaultValue;
}
return defaultValue;
}
return registry.getListTag("value", CompoundTag.class);
}
@@ -62,6 +59,11 @@ public final class TagUtil {
return tag.remove(Key.namespaced(key)) != null || tag.remove(Key.stripMinecraftNamespace(key)) != null;
}
public static @Nullable CompoundTag getNamespacedCompoundTag(final CompoundTag tag, final String key) {
final CompoundTag compoundTag = tag.getCompoundTag(Key.namespaced(key));
return compoundTag != null ? compoundTag : tag.getCompoundTag(Key.stripMinecraftNamespace(key));
}
public static Tag handleDeep(final Tag tag, final TagUpdater consumer) {
return handleDeep(null, tag, consumer);
}
+3 -3
View File
@@ -1,9 +1,9 @@
# Project properties - we put these here so they can be modified without causing a recompile of the build scripts
projectVersion=5.0.0-SNAPSHOT
projectVersion=5.0.0
# Smile emoji
mcVersions=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-1.20.6
mcVersions=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-1.21
velocityVersion=3.3
# Gradle properties
+1 -1
View File
@@ -4,7 +4,7 @@ metadata.format.version = "1.1"
gson = "2.10.1"
fastutil = "8.5.12"
vianbt = "5.0.0-SNAPSHOT"
vianbt = "5.0.0"
mcstructs = "5-2.5.0-SNAPSHOT"
# Common provided
@@ -22,11 +22,15 @@ import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
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;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
@@ -34,6 +38,8 @@ import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.template.protocols.rewriter.BlockItemPacketRewriter1_99;
import com.viaversion.viaversion.template.protocols.rewriter.EntityPacketRewriter1_99;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_99To_98, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99
// ClientboundPacket1_20_5
@@ -64,7 +70,7 @@ public final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND_ENTITY);
new StatisticsRewriter<>(this).register(ClientboundPackets1_20_5.AWARD_STATS);
new AttributeRewriter<>(this).register1_20_5(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES);
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
/*final CommandRewriter1_19_4<ClientboundPackets1_20_5> commandRewriter = new CommandRewriter1_19_4<ClientboundPackets1_20_5>(this) {
@@ -130,4 +136,14 @@ public final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1
public TagRewriter<ClientboundPacket1_20_5> getTagRewriter() {
return tagRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_20_5, ClientboundPacket1_20_5, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}
@@ -46,7 +46,7 @@ public final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Cl
blockRewriter.registerBlockEvent(ClientboundPackets1_20_5.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_20_5.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_20_5.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent(ClientboundPackets1_20_5.LEVEL_EVENT, 1010, 2001);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_20_5.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_20_5.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_20_5.BLOCK_ENTITY_DATA);
@@ -17,6 +17,7 @@
*/
package com.viaversion.viaversion.template.protocols.rewriter;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
@@ -27,6 +28,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.template.protocols.Protocol1_99To_98;
import com.viaversion.viaversion.util.Key;
// Replace if needed
// Types1_OLD
@@ -44,13 +46,10 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
registerSetEntityData(ClientboundPackets1_20_5.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_20_5.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_20_5.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, new PacketHandlers() {
@Override
protected void register() {
map(Types.STRING); // Registry
map(Types.REGISTRY_ENTRY_ARRAY); // Data
handler(registryDataHandler1_20_5()); // Caches dimensions to access data like height later and tracks the amount of biomes sent for chunk data
}
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
final RegistryEntry[] entries = wrapper.passthrough(Types.REGISTRY_ENTRY_ARRAY);
handleRegistryData1_20_5(wrapper.user(), registryKey, entries); // Caches dimensions to access data like height later and tracks the amount of biomes sent for chunk data
});
protocol.registerClientbound(ClientboundPackets1_20_5.LOGIN, new PacketHandlers() {
@@ -72,13 +71,10 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
}
});
protocol.registerClientbound(ClientboundPackets1_20_5.RESPAWN, new PacketHandlers() {
@Override
public void register() {
map(Types.VAR_INT); // Dimension
map(Types.STRING); // World
handler(worldDataTrackerHandlerByKey1_20_5(0)); // Tracks world height and name for chunk data and entity (un)tracking
}
protocol.registerClientbound(ClientboundPackets1_20_5.RESPAWN, wrapper -> {
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
});
}
@@ -99,7 +95,9 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
Types1_20_5.ENTITY_DATA_TYPES.blockStateType,
Types1_20_5.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_20_5.ENTITY_DATA_TYPES.particleType,
Types1_20_5.ENTITY_DATA_TYPES.particlesType
Types1_20_5.ENTITY_DATA_TYPES.particlesType,
Types1_20_5.ENTITY_DATA_TYPES.componentType,
Types1_20_5.ENTITY_DATA_TYPES.optionalComponentType
);
// Minecarts are special
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);