3
0
Mirror von https://github.com/ViaVersion/ViaVersion.git synchronisiert 2024-12-26 16:12:42 +01:00
Dieser Commit ist enthalten in:
Nassim Jahnke 2024-10-02 20:53:00 +02:00
Ursprung 57d5652cd5
Commit f58afd434d
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: EF6771C01F6EF02F
16 geänderte Dateien mit 460 neuen und 164 gelöschten Zeilen

Datei anzeigen

@ -36,4 +36,8 @@ public record RegistryEntry(String key, @Nullable Tag tag) {
public RegistryEntry withKey(final String key) {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
public RegistryEntry copy() {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
}

Datei anzeigen

@ -118,6 +118,8 @@ public enum EntityTypes1_21_2 implements EntityType {
MANGROVE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
OAK_BOAT(ABSTRACT_BOAT),
OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
PALE_OAK_BOAT(ABSTRACT_BOAT),
PALE_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
SPRUCE_BOAT(ABSTRACT_BOAT),
SPRUCE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
@ -209,6 +211,8 @@ public enum EntityTypes1_21_2 implements EntityType {
BREEZE(ABSTRACT_MONSTER),
ZOGLIN(ABSTRACT_MONSTER),
WARDEN(ABSTRACT_MONSTER),
CREAKING(ABSTRACT_MONSTER),
CREAKING_TRANSIENT(ABSTRACT_MONSTER),
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
SKELETON(ABSTRACT_SKELETON),

Datei anzeigen

@ -86,7 +86,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
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-1.21.1", new SubVersionRange("1.21", 0, 1));
public static final ProtocolVersion v1_21_2 = register(768, 211, "1.21.2");
public static final ProtocolVersion v1_21_2 = register(768, 212, "1.21.2");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
public static ProtocolVersion register(int version, String name) {

Datei anzeigen

@ -137,6 +137,12 @@ 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 final DataReader<Particle> TRAIL = (buf, particle) -> {
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Target X
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Target Y
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Target Z
particle.add(Types.INT, buf.readInt()); // Color
};
public static DataReader<Particle> item(Type<Item> item) {
return (buf, particle) -> particle.add(item, item.read(buf));

Datei anzeigen

@ -105,16 +105,19 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
// EntityTypes1_20_5.initialize(this);
// Uncomment if a new particle was added = ids shifted; requires a new Types_ class copied from the last
/*Types1_21.PARTICLE.filler(this)
.reader("block", ParticleType.Readers.BLOCK)
.reader("block_marker", ParticleType.Readers.BLOCK)
.reader("dust", ParticleType.Readers.DUST)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION)
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK)
.reader("item", ParticleType.Readers.item(...));*/
/*Types1_21_2.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("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK)
.reader("entity_effect", ParticleType.Readers.COLOR)
.reader("trail", ParticleType.Readers.TRAIL)
.reader("item", ParticleType.Readers.item(...));*/
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
}

Datei anzeigen

@ -143,11 +143,14 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol<ClientboundPack
.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("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK)
.reader("entity_effect", ParticleType.Readers.COLOR)
.reader("trail", ParticleType.Readers.TRAIL)
.reader("item", ParticleType.Readers.item(Types1_21_2.ITEM));
Types1_21_2.STRUCTURED_DATA.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
StructuredDataKey.UNBREAKABLE, StructuredDataKey.RARITY, StructuredDataKey.HIDE_TOOLTIP, StructuredDataKey.DAMAGE_RESISTANT,

Datei anzeigen

@ -51,6 +51,7 @@ public enum ClientboundPackets1_21_2 implements ClientboundPacket1_21_2 {
DISCONNECT, // 0x1D
DISGUISED_CHAT, // 0x1E
ENTITY_EVENT, // 0x1F
ENTITY_POSITION_SYNC, // 0x73
EXPLODE, // 0x20
FORGET_LEVEL_CHUNK, // 0x21
GAME_EVENT, // 0x22
@ -85,7 +86,10 @@ public enum ClientboundPackets1_21_2 implements ClientboundPacket1_21_2 {
PLAYER_INFO_UPDATE, // 0x3F
PLAYER_LOOK_AT, // 0x40
PLAYER_POSITION, // 0x41
RECIPE, // 0x42
PLAYER_ROTATION, // 0x41
RECIPE_BOOK_ADD, // 0x42
RECIPE_BOOK_REMOVE, // 0x42
RECIPE_BOOK_SETTINGS, // 0x42
REMOVE_ENTITIES, // 0x43
REMOVE_MOB_EFFECT, // 0x44
RESET_SCORE, // 0x45

Datei anzeigen

@ -20,9 +20,9 @@ package com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
@ -38,7 +38,6 @@ 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_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
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_21to1_21_2.Protocol1_21To1_21_2;
@ -51,6 +50,7 @@ import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.TagUtil;
import com.viaversion.viaversion.util.Unit;
import java.util.Set;
public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_21_2, Protocol1_21To1_21_2> {
@ -88,7 +88,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
protocol.registerClientbound(ClientboundPackets1_21.CONTAINER_SET_CONTENT, wrapper -> {
updateContainerId(wrapper);
wrapper.passthrough(Types.VAR_INT); // State id
Item[] items = wrapper.read(itemArrayType());
final Item[] items = wrapper.read(itemArrayType());
wrapper.write(mappedItemArrayType(), items);
for (int i = 0; i < items.length; i++) {
items[i] = handleItemToClient(wrapper.user(), items[i]);
@ -104,10 +104,8 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
protocol.registerClientbound(ClientboundPackets1_21.CONTAINER_CLOSE, this::updateContainerId);
protocol.registerClientbound(ClientboundPackets1_21.CONTAINER_SET_DATA, this::updateContainerId);
protocol.registerClientbound(ClientboundPackets1_21.HORSE_SCREEN_OPEN, this::updateContainerId);
protocol.registerClientbound(ClientboundPackets1_21.PLACE_GHOST_RECIPE, this::updateContainerId);
protocol.registerClientbound(ClientboundPackets1_21.SET_CARRIED_ITEM, ClientboundPackets1_21_2.SET_HELD_SLOT);
protocol.registerServerbound(ServerboundPackets1_21_2.CONTAINER_CLOSE, this::updateContainerIdServerbound);
protocol.registerServerbound(ServerboundPackets1_21_2.PLACE_RECIPE, this::updateContainerIdServerbound);
protocol.registerServerbound(ServerboundPackets1_21_2.CONTAINER_CLICK, wrapper -> {
updateContainerIdServerbound(wrapper);
wrapper.passthrough(Types.VAR_INT); // State id
@ -121,6 +119,26 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
}
passthroughServerboundItem(wrapper);
});
protocol.registerClientbound(ClientboundPackets1_21.PLACE_GHOST_RECIPE, wrapper -> {
this.updateContainerId(wrapper);
final String recipe = wrapper.read(Types.STRING);
wrapper.write(Types.VAR_INT, recipeDisplay(recipe)); // TODO
});
protocol.registerServerbound(ServerboundPackets1_21_2.PLACE_RECIPE, wrapper -> {
this.updateContainerIdServerbound(wrapper);
final String recipe = wrapper.read(Types.STRING);
wrapper.write(Types.VAR_INT, 0); // TODO Display id, from recipe packet
wrapper.cancel();
});
protocol.registerServerbound(ServerboundPackets1_21_2.RECIPE_BOOK_SEEN_RECIPE, wrapper -> {
this.updateContainerIdServerbound(wrapper);
final String recipe = wrapper.read(Types.STRING);
wrapper.write(Types.VAR_INT, 0); // TODO Display id, from recipe packet
wrapper.cancel();
});
protocol.registerServerbound(ServerboundPackets1_21_2.USE_ITEM_ON, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Hand
@ -174,68 +192,64 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
new SoundRewriter<>(protocol).soundHolderHandler().handle(wrapper);
});
new RecipeRewriter1_20_3<>(protocol) {
@Override
protected void handleIngredient(final PacketWrapper wrapper) {
wrapper.write(Types.HOLDER_SET, ingredient(wrapper));
}
protocol.registerClientbound(ClientboundPackets1_21.UPDATE_RECIPES, wrapper -> {
final RecipeRewriter rewriter = new RecipeRewriter(protocol);
wrapper.cancel(); // TODO
@Override
public void handleCraftingShaped(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Group
wrapper.passthrough(Types.VAR_INT); // Crafting book category
final int width = wrapper.passthrough(Types.VAR_INT);
final int height = wrapper.passthrough(Types.VAR_INT);
final int ingredients = width * height;
final int size = wrapper.passthrough(Types.VAR_INT);
int newSize = size;
for (int i = 0; i < size; i++) {
final String recipeIdentifier = wrapper.read(Types.STRING);
wrapper.write(Types.VAR_INT, ingredients);
for (int i = 0; i < ingredients; i++) {
wrapper.write(Types.HOLDER_SET, ingredient(wrapper));
}
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType()))); // Result
wrapper.passthrough(Types.BOOLEAN); // Show notification
}
@Override
public void handleCraftingShapeless(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Group
wrapper.passthrough(Types.VAR_INT); // Crafting book category
final int ingredients = wrapper.read(Types.VAR_INT);
final HolderSet[] ingredient = new HolderSet[ingredients];
for (int i = 0; i < ingredients; i++) {
ingredient[i] = ingredient(wrapper);
}
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType())));
// Also moved below here
wrapper.write(Types.VAR_INT, ingredients);
for (final HolderSet item : ingredient) {
wrapper.write(Types.HOLDER_SET, item);
}
}
private HolderSet ingredient(final PacketWrapper wrapper) {
final Item[] items = wrapper.read(itemArrayType());
final int[] ids = new int[items.length];
for (int i = 0; i < items.length; i++) {
final Item item = rewrite(wrapper.user(), items[i]);
ids[i] = item.identifier();
}
return HolderSet.of(ids);
}
@Override
public void handleRecipeType(final PacketWrapper wrapper, final String type) {
if (type.equals("crafting_special_suspiciousstew") || type.equals("crafting_special_shulkerboxcoloring")) {
wrapper.read(Types.VAR_INT); // Crafting book category
final FullMappings recipeSerializerMappings = protocol.getMappingData().getRecipeSerializerMappings();
final int typeId = wrapper.read(Types.VAR_INT);
final int mappedId = recipeSerializerMappings.getNewId(typeId);
if (mappedId != -1) {
wrapper.write(Types.STRING, recipeIdentifier);
wrapper.write(Types.VAR_INT, mappedId);
} else {
super.handleRecipeType(wrapper, type);
wrapper.set(Types.VAR_INT, 0, --newSize);
}
rewriter.handleRecipeType(wrapper, Key.stripMinecraftNamespace(recipeSerializerMappings.identifier(typeId))); // Use the original
}
}.register1_20_5(ClientboundPackets1_21.UPDATE_RECIPES);
});
protocol.registerClientbound(ClientboundPackets1_21.RECIPE, ClientboundPackets1_21_2.RECIPE_BOOK_ADD, wrapper -> {
final int state = wrapper.passthrough(Types.VAR_INT);
// Pairs of open + filtering for: Crafting, furnace, blast furnace, smoker
final PacketWrapper settingsPacket = wrapper.create(ClientboundPackets1_21_2.RECIPE_BOOK_SETTINGS);
for (int i = 0; i < 4 * 2; i++) {
settingsPacket.write(Types.BOOLEAN, wrapper.read(Types.BOOLEAN));
}
settingsPacket.send(Protocol1_21To1_21_2.class);
// TODO
wrapper.cancel();
final String[] recipes = wrapper.passthrough(Types.STRING_ARRAY);
Set<String> toHighlight = Set.of();
if (state == 0) { // Init (1=Add, 2=Remove)
final String[] highlightRecipes = wrapper.passthrough(Types.STRING_ARRAY);
toHighlight = Set.of(highlightRecipes);
}
wrapper.write(Types.VAR_INT, recipes.length);
for (final String recipe : recipes) {
// Display id
// Display type
// Optional group
// Category type
// Item contents
byte flags = 0;
if (toHighlight.contains(recipe)) {
flags |= (1 << 1); // Highlight
}
wrapper.write(Types.BYTE, flags);
}
});
}
@Override
@ -252,6 +266,18 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
return item;
}
private int recipeDisplay(String type) {
type = Key.stripMinecraftNamespace(type);
return switch (type) {
case "crafting_shapeless" -> 0;
case "crafting_shaped" -> 1;
case "furnace" -> 2;
case "stonecutter" -> 3;
case "smithing" -> 4;
default -> 0;
};
}
private void updateContainerId(final PacketWrapper wrapper) {
// Container id handling was always a bit whack with most reading them as unsigned bytes, some as bytes, some already as var ints.
// In VV they're generally read as unsigned bytesto not have to look the type up every time, but we need to make sure they're

Datei anzeigen

@ -18,9 +18,6 @@
package com.viaversion.viaversion.protocols.v1_21to1_21_2.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_2;
@ -33,12 +30,11 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfi
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_21to1_21_2.Protocol1_21To1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.ClientVehicleStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.TagUtil;
import java.util.Arrays;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
public final class EntityPacketRewriter1_21_2 extends EntityRewriter<ClientboundPacket1_21, Protocol1_21To1_21_2> {
@ -80,32 +76,8 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
instrumentsPacket.send(Protocol1_21To1_21_2.class);
});
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
RegistryEntry[] entries = wrapper.read(Types.REGISTRY_ENTRY_ARRAY);
if (registryKey.equals("enchantment")) {
updateEnchantmentAttributes(entries, protocol.getMappingData().getAttributeMappings());
} else if (registryKey.equals("damage_type")) {
// Add new damage types
final int length = entries.length;
entries = Arrays.copyOf(entries, length + 2);
final CompoundTag enderpearlData = new CompoundTag();
enderpearlData.putString("scaling", "when_caused_by_living_non_player");
enderpearlData.putString("message_id", "fall");
enderpearlData.putFloat("exhaustion", 0.0F);
entries[length] = new RegistryEntry("minecraft:ender_pearl", enderpearlData);
final CompoundTag maceSmashData = new CompoundTag();
maceSmashData.putString("scaling", "when_caused_by_living_non_player");
maceSmashData.putString("message_id", "mace_smash");
maceSmashData.putFloat("exhaustion", 0.1F);
entries[length + 1] = new RegistryEntry("minecraft:mace_smash", maceSmashData);
}
wrapper.write(Types.REGISTRY_ENTRY_ARRAY, entries);
handleRegistryData1_20_5(wrapper.user(), registryKey, entries);
});
final RegistryDataRewriter registryDataRewriter = registryDataRewriter();
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
protocol.registerClientbound(ClientboundPackets1_21.LOGIN, new PacketHandlers() {
@Override
@ -233,6 +205,25 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
wrapper.write(Types.BYTE, updatedFlags);
});
protocol.registerClientbound(ClientboundPackets1_21.TELEPORT_ENTITY, ClientboundPackets1_21_2.ENTITY_POSITION_SYNC, wrapper -> {
wrapper.passthrough(Types.VAR_INT); // Entity ID
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
wrapper.passthrough(Types.DOUBLE); // Z
// Unused...
wrapper.write(Types.DOUBLE, 0D); // Delta movement X
wrapper.write(Types.DOUBLE, 0D); // Delta movement Y
wrapper.write(Types.DOUBLE, 0D); // Delta movement Z
// Unpack y and x rot
final byte yaw = wrapper.read(Types.BYTE);
final byte pitch = wrapper.read(Types.BYTE);
wrapper.write(Types.FLOAT, yaw * 360F / 256F);
wrapper.write(Types.FLOAT, pitch * 360F / 256F);
});
protocol.registerServerbound(ServerboundPackets1_21_2.MOVE_PLAYER_POS, wrapper -> {
wrapper.passthrough(Types.DOUBLE); // X
wrapper.passthrough(Types.DOUBLE); // Y
@ -255,66 +246,25 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
protocol.registerServerbound(ServerboundPackets1_21_2.MOVE_PLAYER_STATUS_ONLY, this::readOnGround);
}
public static void updateEnchantmentAttributes(final RegistryEntry[] entries, final FullMappings mappings) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
private RegistryDataRewriter registryDataRewriter() {
final CompoundTag enderpearlData = new CompoundTag();
enderpearlData.putString("scaling", "when_caused_by_living_non_player");
enderpearlData.putString("message_id", "fall");
enderpearlData.putFloat("exhaustion", 0.0F);
final CompoundTag effects = ((CompoundTag) entry.tag()).getCompoundTag("effects");
if (effects != null) {
updateLocationChangedAttributes(effects, mappings);
updateAttributesFields(effects, mappings);
}
}
}
final CompoundTag maceSmashData = new CompoundTag();
maceSmashData.putString("scaling", "when_caused_by_living_non_player");
maceSmashData.putString("message_id", "mace_smash");
maceSmashData.putFloat("exhaustion", 0.1F);
private static void updateAttributesFields(final CompoundTag effects, final FullMappings mappings) {
final ListTag<CompoundTag> attributesList = TagUtil.getNamespacedCompoundTagList(effects, "attributes");
if (attributesList == null) {
return;
}
for (final CompoundTag attributeData : attributesList) {
updateAttributeField(attributeData, mappings);
}
}
private static void updateLocationChangedAttributes(final CompoundTag effects, final FullMappings mappings) {
final ListTag<CompoundTag> locationChanged = TagUtil.getNamespacedCompoundTagList(effects, "location_changed");
if (locationChanged == null) {
return;
}
for (final CompoundTag data : locationChanged) {
final CompoundTag effect = data.getCompoundTag("effect");
if (effect == null) {
continue;
}
updateAttributeField(effect, mappings);
final ListTag<CompoundTag> innerEffects = effect.getListTag("effects", CompoundTag.class);
if (innerEffects != null) {
for (final CompoundTag innerEffect : innerEffects) {
updateAttributeField(innerEffect, mappings);
}
}
}
}
private static void updateAttributeField(final CompoundTag attributeData, final FullMappings mappings) {
final StringTag attributeTag = attributeData.getStringTag("attribute");
if (attributeTag == null) {
return;
}
final String attribute = Key.stripMinecraftNamespace(attributeTag.getValue());
String mappedAttribute = mappings.mappedIdentifier(attribute);
if (mappedAttribute == null) {
mappedAttribute = mappings.mappedIdentifier(0); // Dummy
}
attributeTag.setValue(mappedAttribute);
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
registryDataRewriter.addEntries(
"damage_type",
new RegistryEntry("minecraft:ender_pearl", enderpearlData),
new RegistryEntry("minecraft:mace_smash", maceSmashData)
);
registryDataRewriter.addEnchantmentEffectRewriter("damage_item", tag -> tag.putString("type", "change_item_damage"));
return registryDataRewriter;
}
private void readOnGround(final PacketWrapper wrapper) {

Datei anzeigen

@ -0,0 +1,94 @@
/*
* 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_21to1_21_2.rewriter;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
final class RecipeRewriter extends RecipeRewriter1_20_3<ClientboundPacket1_21> {
RecipeRewriter(final Protocol<ClientboundPacket1_21, ?, ?, ?> protocol) {
super(protocol);
}
@Override
protected void handleIngredient(final PacketWrapper wrapper) {
wrapper.write(Types.HOLDER_SET, ingredient(wrapper));
}
@Override
public void handleCraftingShaped(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Group
wrapper.passthrough(Types.VAR_INT); // Crafting book category
final int width = wrapper.passthrough(Types.VAR_INT);
final int height = wrapper.passthrough(Types.VAR_INT);
final int ingredients = width * height;
wrapper.write(Types.VAR_INT, ingredients);
for (int i = 0; i < ingredients; i++) {
wrapper.write(Types.HOLDER_SET, ingredient(wrapper));
}
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType()))); // Result
wrapper.passthrough(Types.BOOLEAN); // Show notification
}
@Override
public void handleCraftingShapeless(final PacketWrapper wrapper) {
wrapper.passthrough(Types.STRING); // Group
wrapper.passthrough(Types.VAR_INT); // Crafting book category
final int ingredients = wrapper.read(Types.VAR_INT);
final HolderSet[] ingredient = new HolderSet[ingredients];
for (int i = 0; i < ingredients; i++) {
ingredient[i] = ingredient(wrapper);
}
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType())));
// Also moved below here
wrapper.write(Types.VAR_INT, ingredients);
for (final HolderSet item : ingredient) {
wrapper.write(Types.HOLDER_SET, item);
}
}
private HolderSet ingredient(final PacketWrapper wrapper) {
final Item[] items = wrapper.read(itemArrayType());
final int[] ids = new int[items.length];
for (int i = 0; i < items.length; i++) {
final Item item = rewrite(wrapper.user(), items[i]);
ids[i] = item.identifier();
}
return HolderSet.of(ids);
}
@Override
public void handleRecipeType(final PacketWrapper wrapper, final String type) {
if (type.equals("crafting_special_suspiciousstew") || type.equals("crafting_special_shulkerboxcoloring")) {
wrapper.read(Types.VAR_INT); // Crafting book category
} else {
super.handleRecipeType(wrapper, type);
}
}
}

Datei anzeigen

@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
// Dead as of 1.21.2, the server only sends simple recipe display data instead of full results
public class RecipeRewriter1_21_2<C extends ClientboundPacketType> extends RecipeRewriter1_20_3<C> {
public RecipeRewriter1_21_2(final Protocol<C, ?, ?, ?> protocol) {

Datei anzeigen

@ -88,6 +88,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
int newSize = size;
for (int i = 0; i < size; i++) {
final String recipeIdentifier = wrapper.read(Types.STRING);
// TODO Recipe identifier, then int array item ids and that's it
final FullMappings recipeSerializerMappings = protocol.getMappingData().getRecipeSerializerMappings();
final int typeId = wrapper.read(Types.VAR_INT);
@ -101,6 +102,11 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
handleRecipeType(wrapper, Key.stripMinecraftNamespace(recipeSerializerMappings.identifier(typeId))); // Use the original
}
// Stonecutter recipes on their own
// List of:
// Ingredient (item holder set)
// Slot display id
});
}

Datei anzeigen

@ -0,0 +1,195 @@
/*
* 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.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.data.entity.DimensionData;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.data.entity.DimensionDataImpl;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.TagUtil;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
public class RegistryDataRewriter {
private final Map<String, Consumer<CompoundTag>> enchantmentEffectRewriters = new Object2ObjectArrayMap<>();
private final Map<String, List<RegistryEntry>> toAdd = new Object2ObjectArrayMap<>();
private final Protocol<?, ?, ?, ?> protocol;
public RegistryDataRewriter(Protocol<?, ?, ?, ?> protocol) {
this.protocol = protocol;
}
public void handle(final PacketWrapper wrapper) {
final String registryKey = wrapper.passthrough(Types.STRING);
RegistryEntry[] entries = wrapper.read(Types.REGISTRY_ENTRY_ARRAY);
entries = handle(wrapper.user(), registryKey, entries);
wrapper.write(Types.REGISTRY_ENTRY_ARRAY, entries);
}
public RegistryEntry[] handle(final UserConnection connection, String key, RegistryEntry[] entries) {
key = Key.stripMinecraftNamespace(key);
if (key.equals("enchantment")) {
updateEnchantments(entries);
}
final List<RegistryEntry> toAdd = this.toAdd.get(key);
if (toAdd != null) {
final int length = entries.length;
final int toAddLength = toAdd.size();
entries = Arrays.copyOf(entries, length + toAddLength);
for (int i = 0; i < toAddLength; i++) {
entries[length + i] = toAdd.get(i).copy();
}
}
trackDimensionAndBiomes(connection, key, entries);
return entries;
}
public void addEntries(final String registryKey, final RegistryEntry... entries) {
toAdd.computeIfAbsent(Key.stripMinecraftNamespace(registryKey), $ -> new ArrayList<>()).addAll(List.of(entries));
}
public void addEnchantmentEffectRewriter(final String key, final Consumer<CompoundTag> rewriter) {
enchantmentEffectRewriters.put(Key.stripMinecraftNamespace(key), rewriter);
}
public void trackDimensionAndBiomes(final UserConnection connection, final String registryKey, final RegistryEntry[] entries) {
if (registryKey.equals("worldgen/biome")) {
protocol.getEntityRewriter().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];
final String key = Key.stripMinecraftNamespace(entry.key());
final DimensionData dimensionData = entry.tag() != null
? new DimensionDataImpl(i, (CompoundTag) entry.tag())
: DimensionDataImpl.withDefaultsFor(key, i);
dimensionDataMap.put(key, dimensionData);
}
protocol.getEntityRewriter().tracker(connection).setDimensions(dimensionDataMap);
}
}
public void updateEnchantments(final RegistryEntry[] entries) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag effects = ((CompoundTag) entry.tag()).getCompoundTag("effects");
if (effects == null) {
continue;
}
// Go through all effects, almost all of them may contain an "effect" element
for (final Map.Entry<String, Tag> effectEntry : effects.entrySet()) {
if (effectEntry.getValue() instanceof final CompoundTag compoundTag) {
updateNestedEffect(compoundTag);
} else if (effectEntry.getValue() instanceof final ListTag<?> listTag && listTag.getElementType() == CompoundTag.class) {
for (final Tag tag : listTag) {
updateNestedEffect((CompoundTag) tag);
}
}
}
updateAttributesFields(effects);
}
}
private void updateNestedEffect(final CompoundTag effectsTag) {
final CompoundTag effect = effectsTag.getCompoundTag("effect");
if (effect == null) {
return;
}
runEffectRewriters(effect);
final ListTag<CompoundTag> innerEffects = effect.getListTag("effects", CompoundTag.class);
if (innerEffects == null) {
return;
}
for (final CompoundTag innerEffect : innerEffects) {
runEffectRewriters(innerEffect);
}
}
private void updateAttributesFields(final CompoundTag effects) {
if (!hasAttributeMappings()) {
return;
}
final ListTag<CompoundTag> attributesList = TagUtil.getNamespacedCompoundTagList(effects, "attributes");
if (attributesList == null) {
return;
}
for (final CompoundTag attributeData : attributesList) {
updateAttributeField(attributeData);
}
}
private void runEffectRewriters(final CompoundTag effectTag) {
String effect = effectTag.getString("type");
if (effect == null) {
return;
}
effect = Key.stripMinecraftNamespace(effect);
updateAttributeField(effectTag);
final Consumer<CompoundTag> rewriter = enchantmentEffectRewriters.get(effect);
if (rewriter != null) {
rewriter.accept(effectTag);
}
}
private void updateAttributeField(final CompoundTag attributeData) {
final StringTag attributeTag = attributeData.getStringTag("attribute");
if (attributeTag == null) {
return;
}
final FullMappings mappings = protocol.getMappingData().getAttributeMappings();
final String attribute = Key.stripMinecraftNamespace(attributeTag.getValue());
String mappedAttribute = mappings.mappedIdentifier(attribute);
if (mappedAttribute == null) {
mappedAttribute = mappings.mappedIdentifier(0); // Dummy
}
attributeTag.setValue(mappedAttribute);
}
private boolean hasAttributeMappings() {
return protocol.getMappingData() != null && protocol.getMappingData().getAttributeMappings() != null;
}
}