3
0
Mirror von https://github.com/ViaVersion/ViaVersion.git synchronisiert 2024-12-27 00:22:51 +01:00

Merge branch 'master' into component-rewriter-work

# Conflicts:
#	common/src/main/java/com/viaversion/viaversion/protocols/v1_20_3to1_20_5/rewriter/ComponentRewriter1_20_5.java
Dieser Commit ist enthalten in:
FlorianMichael 2024-12-14 22:19:29 +01:00
Commit 13fa72435c
213 geänderte Dateien mit 8661 neuen und 2060 gelöschten Zeilen

1
.github/FUNDING.yml vendored
Datei anzeigen

@ -1,2 +1,3 @@
github: kennytv
patreon: kennytv
custom: ['https://florianmichael.de/donate']

Datei anzeigen

@ -21,10 +21,11 @@ body:
- type: textarea
attributes:
label: Console Error
label: Server/Client Error
description: |
If you encounter warnings/errors in your console, **paste them with https://mclo.gs/ and put the paste link here**.
If the error is small/less than 10 lines, you may put it directly into this field.
**Important**: If you are kicked for `Network Protocol Error` or an encoder/decoder exception, please click the `Open Report Directory` button on your client and paste the newest disconnect file contents.
value: |
```
Put the mclo.gs link or text here.
@ -51,7 +52,7 @@ body:
List the steps on how we can reproduce the issue. Make sure we can easily understand what you mean with each step.
placeholder: |
Example:
1. Login with a 1.13.2 client
1. Login with a 1.21.3 client
2. Place a sign
3. The sign text is displayed wrong
validations:

5
.gitignore vendored
Datei anzeigen

@ -109,4 +109,7 @@ nb-configuration.xml
.nb-gradle/
### MacOS ###
.DS_Store
.DS_Store
### Run Folder (ViaProxy) ###
common/run/

Datei anzeigen

@ -20,6 +20,13 @@ Supported Versions:
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
Snapshot support
--------
**ViaVersion will only be released a few days *after* a Minecraft update** unless the protocol changes of the update were trivial. If you want early-access, usually days or even weeks before the final release, you can subscribe to either:
- [GitHub Sponsors](https://github.com/sponsors/kennytv/sponsorships?sponsor=kennytv&tier_id=385613&preview=false) (preferred option. Use the `/verify` command on this Discord after), or alternatively
- [Patreon](https://www.patreon.com/kennytv/membership) (see the highest tier and make sure to link Patreon to your Discord account under Settings->Connections)
This also includes access to a private repository with the code, which will be pushed to the public repository after the given delay on a Minecraft update.
Releases/Dev Builds
--------
You can find official releases in the following places:
@ -91,8 +98,7 @@ Resources
- **[Via Mappings Generator](https://github.com/ViaVersion/Mappings)**
- **[Mojang mappings](https://minecraft.wiki/w/Obfuscation_map)** (Thank you, Mojang, very cool)
- **[wiki.vg](https://wiki.vg)** (Used for historic information regarding packet structure, we also contribute back)
- **[Burger](https://github.com/Pokechu22/Burger)** (See [PAaaS](https://github.com/Matsv/Paaas))
- Previously: **[Burger](https://github.com/Pokechu22/Burger)** (see [PAaaS](https://github.com/Matsv/Paaas)) and **wiki.vg**
License
--------

Datei anzeigen

@ -19,7 +19,9 @@ dependencies {
api(libs.vianbt) {
exclude("it.unimi.dsi", "fastutil")
}
api(libs.gson)
api(libs.gson) {
exclude("com.google.errorprone", "error_prone_annotations")
}
implementation(rootProject.libs.text) {
exclude("com.google.code.gson", "gson")
exclude("com.viaversion", "nbt")

Datei anzeigen

@ -53,6 +53,14 @@ public interface FullMappings extends BiMappings {
*/
@Nullable String identifier(int id);
/**
* Returns the unmapped string identifier for the given mapped identifier.
*
* @param mappedIdentifier mapped identifier
* @return unmapped string identifier, or null if not found
*/
@Nullable String identifier(String mappedIdentifier);
/**
* Returns the mapped string identifier for the given mapped id.
*

Datei anzeigen

@ -84,7 +84,18 @@ public class FullMappingsBase implements FullMappings {
}
@Override
public String mappedIdentifier(final int mappedId) {
public @Nullable String identifier(final String mappedIdentifier) {
final int mappedId = mappedId(mappedIdentifier);
if (mappedId == -1) {
return null;
}
final int id = mappings.inverse().getNewId(mappedId);
return id != -1 ? identifier(id) : null;
}
@Override
public @Nullable String mappedIdentifier(final int mappedId) {
if (mappedId < 0 || mappedId >= mappedIdToString.length) {
return null;
}

Datei anzeigen

@ -35,56 +35,82 @@ public interface MappingData {
void load();
/**
* Returns the mapped block state id, or -1 if unmapped.
* Returns the mapped block state id, or 0 if unmapped.
*
* @param id unmapped block state id
* @return mapped block state id, or -1 if unmapped
* @return mapped block state id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold block state mappings
*/
int getNewBlockStateId(int id);
/**
* Returns the mapped block id, or -1 if unmapped.
* Returns the mapped block id, or 0 if unmapped.
*
* @param id unmapped block id
* @return mapped block id, or -1 if unmapped
* @return mapped block id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold block mappings
*/
int getNewBlockId(int id);
/**
* Returns the backwards mapped block id, or 1 if unmapped.
*
* @param id mapped block id
* @return backwards mapped block id, or 1 if unmapped
*/
int getOldBlockId(int id);
/**
* Returns the mapped item id, or -1 if unmapped.
* Returns the mapped item id, or 0 if unmapped.
*
* @param id unmapped item id
* @return mapped item id, or -1 if unmapped
* @return mapped item id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold item mappings
*/
int getNewItemId(int id);
/**
* Returns the backwards mapped item id, or -1 if unmapped.
* Returns the backwards mapped item id, or 1 if unmapped.
*
* @param id mapped item id
* @return backwards mapped item id, or -1 if unmapped
* @return backwards mapped item id, or 1 if unmapped
* @throws NullPointerException if this mappingdata does not hold item mappings
*/
int getOldItemId(int id);
/**
* Returns the mapped particle id, or -1 if unmapped.
* Returns the mapped particle id, or 0 if unmapped.
*
* @param id unmapped particle id
* @return mapped particle id, or -1 if unmapped
* @return mapped particle id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold particle mappings
*/
int getNewParticleId(int id);
/**
* Returns the mapped attribute id, or 0 if unmapped.
*
* @param id unmapped attribute id
* @return mapped attribute id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold attribute mappings
*/
int getNewAttributeId(int id);
/**
* Returns the mapped sound id, or 0 if unmapped.
*
* @param id unmapped sound id
* @return mapped sound id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold sound mappings
*/
int getNewSoundId(int id);
/**
* Returns the backwards mapped sound id, or 1 if unmapped.
*
* @param i mapped sound id
* @return backwards mapped sound id, or 1 if unmapped
*/
int getOldSoundId(int i);
/**
@ -126,10 +152,10 @@ public interface MappingData {
@Nullable Mappings getEnchantmentMappings();
@Nullable Mappings getAttributeMappings();
@Nullable Mappings getPaintingMappings();
@Nullable FullMappings getAttributeMappings();
@Nullable FullMappings getEntityMappings();
@Nullable FullMappings getArgumentTypeMappings();

Datei anzeigen

@ -43,10 +43,10 @@ public class MappingDataBase implements MappingData {
protected FullMappings entityMappings;
protected FullMappings recipeSerializerMappings;
protected FullMappings itemDataSerializerMappings;
protected FullMappings attributeMappings;
protected ParticleMappings particleMappings;
protected BiMappings itemMappings;
protected BiMappings blockMappings;
protected BiMappings attributeMappings;
protected Mappings blockStateMappings;
protected Mappings blockEntityMappings;
protected Mappings soundMappings;
@ -76,8 +76,6 @@ public class MappingDataBase implements MappingData {
menuMappings = loadMappings(data, "menus");
enchantmentMappings = loadMappings(data, "enchantments");
paintingMappings = loadMappings(data, "paintings");
attributeMappings = loadBiMappings(data, "attributes");
final CompoundTag unmappedIdentifierData = readUnmappedIdentifiersFile("identifiers-" + unmappedVersion + ".nbt");
final CompoundTag mappedIdentifierData = readMappedIdentifiersFile("identifiers-" + mappedVersion + ".nbt");
@ -87,6 +85,7 @@ public class MappingDataBase implements MappingData {
argumentTypeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "argumenttypes");
recipeSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "recipe_serializers");
itemDataSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "data_component_type");
attributeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "attributes");
final List<String> unmappedParticles = identifiersFromGlobalIds(unmappedIdentifierData, "particles");
final List<String> mappedParticles = identifiersFromGlobalIds(mappedIdentifierData, "particles");
@ -180,7 +179,7 @@ public class MappingDataBase implements MappingData {
@Override
public int getOldBlockId(final int id) {
return blockMappings.getNewIdOrDefault(id, 1);
return blockMappings.inverse().getNewIdOrDefault(id, 1);
}
@Override
@ -272,7 +271,7 @@ public class MappingDataBase implements MappingData {
}
@Override
public @Nullable Mappings getAttributeMappings() {
public @Nullable FullMappings getAttributeMappings() {
return attributeMappings;
}

Datei anzeigen

@ -36,6 +36,7 @@ public class ParticleMappings extends FullMappingsBase {
addBlockParticle("falling_dust");
addBlockParticle("block_marker");
addBlockParticle("dust_pillar");
addBlockParticle("block_crumble");
addItemParticle("item");
}

Datei anzeigen

@ -78,7 +78,7 @@ public interface DebugHandler {
/**
* Returns whether packets should be logged after being transformed.
* Set to true by default.
* Set to false by default.
*
* @return whether packets should be logged after being transformed
*/

Datei anzeigen

@ -37,6 +37,13 @@ public class BlockPosition {
return new BlockPosition(x + face.modX(), y + face.modY(), z + face.modZ());
}
public double distanceFromCenterSquared(final double x, final double y, final double z) {
final double dx = this.x + 0.5 - x;
final double dy = this.y + 0.5 - y;
final double dz = this.z + 0.5 - z;
return dx * dx + dy * dy + dz * dz;
}
public int x() {
return x;
}

Datei anzeigen

@ -66,6 +66,17 @@ public final class ChunkPosition {
return (long) chunkX & 0xffffffffL | ((long) chunkZ & 0xffffffffL) << 32;
}
/**
* Returns a long key for the given block coordinates.
*
* @param x the block X coordinate
* @param z the block Z coordinate
* @return the chunk key
*/
public static long chunkKeyForBlock(final int x, final int z) {
return chunkKey(x >> 4, z >> 4);
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;

Datei anzeigen

@ -35,7 +35,7 @@ public interface Holder<T> {
* @throws IllegalArgumentException if the id is negative
*/
static <T> Holder<T> of(final int id) {
return new HolderImpl<>(id);
return new IdHolder<>(id);
}
/**
@ -46,7 +46,7 @@ public interface Holder<T> {
* @return a new direct holder
*/
static <T> Holder<T> of(final T value) {
return new HolderImpl<>(value);
return new ValueHolder<>(value);
}
/**

Datei anzeigen

@ -36,7 +36,7 @@ public interface HolderSet {
* @return a new holder set
*/
static HolderSet of(final String tagKey) {
return new HolderSetImpl(tagKey);
return new HolderSetImpl.Tag(tagKey);
}
/**
@ -46,7 +46,7 @@ public interface HolderSet {
* @return a new holder set
*/
static HolderSet of(final int[] ids) {
return new HolderSetImpl(ids);
return new HolderSetImpl.Ids(ids);
}
/**

Datei anzeigen

@ -22,50 +22,63 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.EitherImpl;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.Arrays;
final class HolderSetImpl extends EitherImpl<String, int[]> implements HolderSet {
final class HolderSetImpl {
HolderSetImpl(final String tagKey) {
super(tagKey, null);
}
record Tag(String tagKey) implements HolderSet {
@Override
public boolean hasTagKey() {
return true;
}
HolderSetImpl(final int[] ids) {
super(null, ids);
}
@Override
public int[] ids() {
throw new IllegalArgumentException("This holder set has a tag key");
}
@Override
public String tagKey() {
return left();
}
@Override
public boolean hasIds() {
return false;
}
@Override
public boolean hasTagKey() {
return isLeft();
}
@Override
public int[] ids() {
return right();
}
@Override
public boolean hasIds() {
return isRight();
}
@Override
public HolderSet rewrite(final Int2IntFunction idRewriter) {
if (hasTagKey()) {
@Override
public HolderSet rewrite(final Int2IntFunction idRewriter) {
return this;
}
}
final int[] ids = ids();
final int[] mappedIds = new int[ids.length];
for (int i = 0; i < mappedIds.length; i++) {
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
record Ids(int[] ids) implements HolderSet {
@Override
public boolean hasTagKey() {
return false;
}
@Override
public String tagKey() {
throw new IllegalArgumentException("This holder set has direct ids");
}
@Override
public boolean hasIds() {
return true;
}
@Override
public HolderSet rewrite(final Int2IntFunction idRewriter) {
final int[] mappedIds = new int[ids.length];
for (int i = 0; i < mappedIds.length; i++) {
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
}
return new Ids(mappedIds);
}
@Override
public String toString() {
return "Ids{" +
"ids=" + Arrays.toString(ids) +
'}';
}
return new HolderSetImpl(mappedIds);
}
}

Datei anzeigen

@ -25,49 +25,29 @@ package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
final class HolderImpl<T> implements Holder<T> {
record IdHolder<T>(int id) implements Holder<T> {
private final T value;
private final int id;
HolderImpl(final int id) {
IdHolder {
Preconditions.checkArgument(id >= 0, "id cannot be negative");
this.value = null;
this.id = id;
}
HolderImpl(final T value) {
this.value = value;
this.id = -1;
}
@Override
public boolean isDirect() {
return id == -1;
return false;
}
@Override
public boolean hasId() {
return id != -1;
return true;
}
@Override
public T value() {
Preconditions.checkArgument(isDirect(), "Holder is not direct");
return value;
}
@Override
public int id() {
return id;
throw new IllegalArgumentException("Holder is not direct");
}
@Override
public Holder<T> updateId(final Int2IntFunction rewriteFunction) {
if (isDirect()) {
return this;
}
final int rewrittenId = rewriteFunction.applyAsInt(id);
if (rewrittenId == id) {
return this;
@ -77,12 +57,4 @@ final class HolderImpl<T> implements Holder<T> {
}
return Holder.of(rewrittenId);
}
@Override
public String toString() {
return "HolderImpl{" +
"value=" + value +
", id=" + id +
'}';
}
}

Datei anzeigen

@ -22,13 +22,19 @@
*/
package com.viaversion.viaversion.api.minecraft;
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 org.checkerframework.checker.nullness.qual.Nullable;
public record PaintingVariant(int width, int height, String assetId) {
public record PaintingVariant(int width, int height, String assetId, @Nullable Tag title, @Nullable Tag author) {
public static HolderType<PaintingVariant> TYPE = new HolderType<>() {
public PaintingVariant(final int width, final int height, final String assetId) {
this(width, height, assetId, null, null);
}
public static HolderType<PaintingVariant> TYPE1_21 = new HolderType<>() {
@Override
public PaintingVariant readDirect(final ByteBuf buffer) {
final int width = Types.VAR_INT.readPrimitive(buffer);
@ -44,4 +50,24 @@ public record PaintingVariant(int width, int height, String assetId) {
Types.STRING.write(buffer, variant.assetId());
}
};
public static HolderType<PaintingVariant> TYPE1_21_2 = new HolderType<>() {
@Override
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);
final Tag title = Types.OPTIONAL_TAG.read(buffer);
final Tag author = Types.OPTIONAL_TAG.read(buffer);
return new PaintingVariant(width, height, assetId, title, author);
}
@Override
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());
Types.OPTIONAL_TAG.write(buffer, variant.title());
Types.OPTIONAL_TAG.write(buffer, variant.author());
}
};
}

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

@ -0,0 +1,48 @@
/*
* 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;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
record ValueHolder<T>(T value) implements Holder<T> {
@Override
public boolean isDirect() {
return true;
}
@Override
public boolean hasId() {
return false;
}
@Override
public int id() {
return -1;
}
@Override
public Holder<T> updateId(final Int2IntFunction rewriteFunction) {
return this;
}
}

Datei anzeigen

@ -37,14 +37,14 @@ public class ChunkSectionImpl implements ChunkSection {
public ChunkSectionImpl(final boolean holdsLight) {
addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE));
if (holdsLight) {
this.light = new ChunkSectionLightImpl();
this.light = ChunkSectionLightImpl.createWithBlockLight();
}
}
public ChunkSectionImpl(final boolean holdsLight, final int expectedPaletteLength) {
addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE, expectedPaletteLength));
if (holdsLight) {
this.light = new ChunkSectionLightImpl();
this.light = ChunkSectionLightImpl.createWithBlockLight();
}
}

Datei anzeigen

@ -35,7 +35,7 @@ public interface ChunkSectionLight {
/**
* Returns whether the section has sky light.
*
* @return true if skylight is present
* @return true if sky light is present
*/
boolean hasSkyLight();
@ -43,7 +43,7 @@ public interface ChunkSectionLight {
* Returns whether the section has block light.
* This returns true unless specifically set to null.
*
* @return true if skylight is present
* @return true if block light is present
*/
boolean hasBlockLight();

Datei anzeigen

@ -30,9 +30,17 @@ public class ChunkSectionLightImpl implements ChunkSectionLight {
private NibbleArray blockLight;
private NibbleArray skyLight;
public ChunkSectionLightImpl() {
// Block light is always written
this.blockLight = new NibbleArray(ChunkSection.SIZE);
protected ChunkSectionLightImpl() {
}
public static ChunkSectionLight createWithBlockLight() {
final ChunkSectionLightImpl light = new ChunkSectionLightImpl();
light.blockLight = new NibbleArray(ChunkSection.SIZE);
return light;
}
public static ChunkSectionLight createEmpty() {
return new ChunkSectionLightImpl();
}
@Override

Datei anzeigen

@ -26,6 +26,7 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.GameProfile;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
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;
@ -34,13 +35,20 @@ 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;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant;
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.data.Equippable;
import com.viaversion.viaversion.api.minecraft.item.data.FilterableString;
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.FoodProperties1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
@ -48,11 +56,15 @@ import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable;
import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
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.ArrayType;
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.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
import com.viaversion.viaversion.util.Unit;
public record StructuredDataKey<T>(String identifier, Type<T> type) {
@ -64,24 +76,38 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Unbreakable> UNBREAKABLE = new StructuredDataKey<>("unbreakable", Unbreakable.TYPE);
public static final StructuredDataKey<Tag> CUSTOM_NAME = new StructuredDataKey<>("custom_name", Types.TAG);
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TAG);
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", Types.TAG_ARRAY);
public static final StructuredDataKey<String> ITEM_MODEL = new StructuredDataKey<>("item_model", Types.STRING);
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", new ArrayType<>(Types.TAG, 256));
public static final StructuredDataKey<Integer> RARITY = new StructuredDataKey<>("rarity", Types.VAR_INT);
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<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<Integer> CUSTOM_MODEL_DATA1_20_5 = new StructuredDataKey<>("custom_model_data", Types.VAR_INT);
public static final StructuredDataKey<CustomModelData1_21_4> CUSTOM_MODEL_DATA1_21_4 = new StructuredDataKey<>("custom_model_data", CustomModelData1_21_4.TYPE);
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);
public static final StructuredDataKey<Integer> REPAIR_COST = new StructuredDataKey<>("repair_cost", Types.VAR_INT);
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> 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<FoodProperties1_20_5> FOOD1_20_5 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_20_5);
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_21);
public static final StructuredDataKey<FoodProperties1_21_2> FOOD1_21_2 = new StructuredDataKey<>("food", FoodProperties1_21_2.TYPE);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
public static final StructuredDataKey<Item> USE_REMAINDER1_21_2 = new StructuredDataKey<>("use_remainder", Types1_21_2.ITEM);
public static final StructuredDataKey<Item> USE_REMAINDER1_21_4 = new StructuredDataKey<>("use_remainder", Types1_21_4.ITEM);
public static final StructuredDataKey<UseCooldown> USE_COOLDOWN = new StructuredDataKey<>("use_cooldown", UseCooldown.TYPE);
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
public static final StructuredDataKey<DamageResistant> DAMAGE_RESISTANT = new StructuredDataKey<>("damage_resistant", DamageResistant.TYPE);
public static final StructuredDataKey<ToolProperties> TOOL = new StructuredDataKey<>("tool", ToolProperties.TYPE);
public static final StructuredDataKey<Integer> ENCHANTABLE = new StructuredDataKey<>("enchantable", Types.VAR_INT);
public static final StructuredDataKey<Equippable> EQUIPPABLE = new StructuredDataKey<>("equippable", Equippable.TYPE);
public static final StructuredDataKey<HolderSet> REPAIRABLE = new StructuredDataKey<>("repairable", Types.HOLDER_SET);
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
public static final StructuredDataKey<String> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.STRING);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE);
public static final StructuredDataKey<DyedColor> DYED_COLOR = new StructuredDataKey<>("dyed_color", DyedColor.TYPE);
public static final StructuredDataKey<Integer> MAP_COLOR = new StructuredDataKey<>("map_color", Types.INT);
@ -90,18 +116,26 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> MAP_POST_PROCESSING = new StructuredDataKey<>("map_post_processing", Types.VAR_INT);
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[]> CHARGED_PROJECTILES1_21_2 = new StructuredDataKey<>("charged_projectiles", Types1_21_2.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_4 = new StructuredDataKey<>("charged_projectiles", Types1_21_4.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<Item[]> BUNDLE_CONTENTS1_21_2 = new StructuredDataKey<>("bundle_contents", Types1_21_2.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_4 = new StructuredDataKey<>("bundle_contents", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_20_5 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_20_5);
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_21_2 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_21_2);
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);
public static final StructuredDataKey<WrittenBook> WRITTEN_BOOK_CONTENT = new StructuredDataKey<>("written_book_content", WrittenBook.TYPE);
public static final StructuredDataKey<ArmorTrim> TRIM = new StructuredDataKey<>("trim", ArmorTrim.TYPE);
public static final StructuredDataKey<ArmorTrim> TRIM1_20_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_20_5);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_2 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_2);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_4 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_4);
public static final StructuredDataKey<CompoundTag> DEBUG_STICK_STATE = new StructuredDataKey<>("debug_stick_state", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> ENTITY_DATA = new StructuredDataKey<>("entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> BUCKET_ENTITY_DATA = new StructuredDataKey<>("bucket_entity_data", Types.COMPOUND_TAG);
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<Holder<Instrument1_20_5>> INSTRUMENT1_20_5 = new StructuredDataKey<>("instrument", Instrument1_20_5.TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT1_21_2 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
public static final StructuredDataKey<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);
@ -115,6 +149,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
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<Item[]> CONTAINER1_21_2 = new StructuredDataKey<>("container", new ArrayType<>(Types1_21_2.ITEM, 256));
public static final StructuredDataKey<Item[]> CONTAINER1_21_4 = new StructuredDataKey<>("container", Types1_21_4.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);

Datei anzeigen

@ -0,0 +1,314 @@
/*
* 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.entities;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.EntityTypeUtil;
import com.viaversion.viaversion.util.Key;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum EntityTypes1_21_2 implements EntityType {
ENTITY(null, null),
AREA_EFFECT_CLOUD(ENTITY),
END_CRYSTAL(ENTITY),
EVOKER_FANGS(ENTITY),
EXPERIENCE_ORB(ENTITY),
EYE_OF_ENDER(ENTITY),
FALLING_BLOCK(ENTITY),
ITEM(ENTITY),
TNT(ENTITY),
OMINOUS_ITEM_SPAWNER(ENTITY),
MARKER(ENTITY),
LIGHTNING_BOLT(ENTITY),
INTERACTION(ENTITY),
DISPLAY(ENTITY, null),
BLOCK_DISPLAY(DISPLAY),
ITEM_DISPLAY(DISPLAY),
TEXT_DISPLAY(DISPLAY),
// Hanging entities
HANGING_ENTITY(ENTITY, null),
LEASH_KNOT(HANGING_ENTITY),
PAINTING(HANGING_ENTITY),
ITEM_FRAME(HANGING_ENTITY),
GLOW_ITEM_FRAME(ITEM_FRAME),
// Projectiles
PROJECTILE(ENTITY, null),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
FISHING_BOBBER(PROJECTILE),
WITHER_SKULL(PROJECTILE),
DRAGON_FIREBALL(PROJECTILE), // Doesn't actually inherit fireball
ABSTRACT_ARROW(PROJECTILE, null),
ARROW(ABSTRACT_ARROW),
SPECTRAL_ARROW(ABSTRACT_ARROW),
TRIDENT(ABSTRACT_ARROW),
ABSTRACT_FIREBALL(ENTITY, null),
FIREBALL(ABSTRACT_FIREBALL),
SMALL_FIREBALL(ABSTRACT_FIREBALL),
ABSTRACT_WIND_CHARGE(PROJECTILE, null),
WIND_CHARGE(ABSTRACT_WIND_CHARGE),
BREEZE_WIND_CHARGE(ABSTRACT_WIND_CHARGE),
// Vehicles
VEHICLE(ENTITY, null),
ABSTRACT_MINECART(VEHICLE, null),
MINECART(ABSTRACT_MINECART),
FURNACE_MINECART(ABSTRACT_MINECART),
COMMAND_BLOCK_MINECART(ABSTRACT_MINECART),
TNT_MINECART(ABSTRACT_MINECART),
SPAWNER_MINECART(ABSTRACT_MINECART),
ABSTRACT_MINECART_CONTAINER(ABSTRACT_MINECART, null),
CHEST_MINECART(ABSTRACT_MINECART_CONTAINER),
HOPPER_MINECART(ABSTRACT_MINECART_CONTAINER),
ABSTRACT_BOAT(VEHICLE, null),
ABSTRACT_CHEST_BOAT(ABSTRACT_BOAT, null),
ACACIA_BOAT(ABSTRACT_BOAT),
ACACIA_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
BAMBOO_CHEST_RAFT(ABSTRACT_CHEST_BOAT),
BAMBOO_RAFT(ABSTRACT_BOAT),
BIRCH_BOAT(ABSTRACT_BOAT),
BIRCH_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
CHERRY_BOAT(ABSTRACT_BOAT),
CHERRY_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
DARK_OAK_BOAT(ABSTRACT_BOAT),
DARK_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
JUNGLE_BOAT(ABSTRACT_BOAT),
JUNGLE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
MANGROVE_BOAT(ABSTRACT_BOAT),
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),
// Living entities as a larger subclass
LIVING_ENTITY(ENTITY, null),
ARMOR_STAND(LIVING_ENTITY),
PLAYER(LIVING_ENTITY),
// Mobs as a larger subclass
MOB(LIVING_ENTITY, null),
ENDER_DRAGON(MOB),
SLIME(MOB),
MAGMA_CUBE(SLIME),
// Ambient mobs
AMBIENT_CREATURE(MOB, null),
BAT(AMBIENT_CREATURE),
// Flying mobs
FLYING_MOB(MOB, null),
GHAST(FLYING_MOB),
PHANTOM(FLYING_MOB),
// Pathfinder mobs and its subclasses
PATHFINDER_MOB(MOB, null),
ALLAY(PATHFINDER_MOB),
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
SNOW_GOLEM(ABSTRACT_GOLEM),
IRON_GOLEM(ABSTRACT_GOLEM),
SHULKER(ABSTRACT_GOLEM),
// Ageable mobs and (tamable) animals
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
VILLAGER(ABSTRACT_VILLAGER),
WANDERING_TRADER(ABSTRACT_VILLAGER),
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
AXOLOTL(ABSTRACT_ANIMAL),
CHICKEN(ABSTRACT_ANIMAL),
PANDA(ABSTRACT_ANIMAL),
PIG(ABSTRACT_ANIMAL),
POLAR_BEAR(ABSTRACT_ANIMAL),
RABBIT(ABSTRACT_ANIMAL),
SHEEP(ABSTRACT_ANIMAL),
BEE(ABSTRACT_ANIMAL),
TURTLE(ABSTRACT_ANIMAL),
FOX(ABSTRACT_ANIMAL),
FROG(ABSTRACT_ANIMAL),
GOAT(ABSTRACT_ANIMAL),
HOGLIN(ABSTRACT_ANIMAL),
STRIDER(ABSTRACT_ANIMAL),
SNIFFER(ABSTRACT_ANIMAL),
ARMADILLO(ABSTRACT_ANIMAL),
COW(ABSTRACT_ANIMAL),
MOOSHROOM(COW),
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
CAT(TAMABLE_ANIMAL),
OCELOT(TAMABLE_ANIMAL),
WOLF(TAMABLE_ANIMAL),
PARROT(TAMABLE_ANIMAL),
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
HORSE(ABSTRACT_HORSE),
SKELETON_HORSE(ABSTRACT_HORSE),
ZOMBIE_HORSE(ABSTRACT_HORSE),
CAMEL(ABSTRACT_HORSE),
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
DONKEY(ABSTRACT_CHESTED_HORSE),
MULE(ABSTRACT_CHESTED_HORSE),
LLAMA(ABSTRACT_CHESTED_HORSE),
TRADER_LLAMA(LLAMA),
// Monsters
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
BLAZE(ABSTRACT_MONSTER),
CREEPER(ABSTRACT_MONSTER),
ENDERMITE(ABSTRACT_MONSTER),
ENDERMAN(ABSTRACT_MONSTER),
GIANT(ABSTRACT_MONSTER),
SILVERFISH(ABSTRACT_MONSTER),
VEX(ABSTRACT_MONSTER),
WITHER(ABSTRACT_MONSTER),
BREEZE(ABSTRACT_MONSTER),
ZOGLIN(ABSTRACT_MONSTER),
WARDEN(ABSTRACT_MONSTER),
CREAKING(ABSTRACT_MONSTER),
CREAKING_TRANSIENT(CREAKING),
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
SKELETON(ABSTRACT_SKELETON),
STRAY(ABSTRACT_SKELETON),
WITHER_SKELETON(ABSTRACT_SKELETON),
BOGGED(ABSTRACT_SKELETON),
ZOMBIE(ABSTRACT_MONSTER),
DROWNED(ZOMBIE),
HUSK(ZOMBIE),
ZOMBIFIED_PIGLIN(ZOMBIE),
ZOMBIE_VILLAGER(ZOMBIE),
GUARDIAN(ABSTRACT_MONSTER),
ELDER_GUARDIAN(GUARDIAN),
SPIDER(ABSTRACT_MONSTER),
CAVE_SPIDER(SPIDER),
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
PIGLIN(ABSTRACT_PIGLIN),
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
// Water mobs
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
DOLPHIN(AGEABLE_WATER_CREATURE),
SQUID(AGEABLE_WATER_CREATURE),
GLOW_SQUID(SQUID),
WATER_ANIMAL(PATHFINDER_MOB, null),
ABSTRACT_FISH(WATER_ANIMAL, null),
PUFFERFISH(ABSTRACT_FISH),
TADPOLE(ABSTRACT_FISH),
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
COD(ABSTRACT_SCHOOLING_FISH),
SALMON(ABSTRACT_SCHOOLING_FISH),
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
// Raiders
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
WITCH(ABSTRACT_RAIDER),
RAVAGER(ABSTRACT_RAIDER),
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
VINDICATOR(ABSTRACT_ILLAGER),
PILLAGER(ABSTRACT_ILLAGER),
EVOKER(SPELLCASTER_ILLAGER),
ILLUSIONER(SPELLCASTER_ILLAGER);
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
private final EntityType parent;
private final String identifier;
private int id = -1;
EntityTypes1_21_2(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes1_21_2(final EntityType parent, @Nullable final String identifier) {
this.parent = parent;
this.identifier = identifier;
}
@Override
public int getId() {
if (id == -1) {
throw new IllegalStateException("Ids have not been initialized yet (type " + name() + ")");
}
return id;
}
@Override
public String identifier() {
Preconditions.checkArgument(identifier != null, "Called identifier method on abstract type");
return identifier;
}
@Override
public @Nullable EntityType getParent() {
return parent;
}
@Override
public boolean isAbstractType() {
return identifier == null;
}
public static EntityType getTypeFromId(final int typeId) {
return EntityTypeUtil.getTypeFromId(TYPES, typeId, ENTITY);
}
public static void initialize(final Protocol<?, ?, ?, ?> protocol) {
EntityTypeUtil.initialize(values(), TYPES, protocol, (type, id) -> type.id = id);
}
}

Datei anzeigen

@ -0,0 +1,313 @@
/*
* 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.entities;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.EntityTypeUtil;
import com.viaversion.viaversion.util.Key;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum EntityTypes1_21_4 implements EntityType {
ENTITY(null, null),
AREA_EFFECT_CLOUD(ENTITY),
END_CRYSTAL(ENTITY),
EVOKER_FANGS(ENTITY),
EXPERIENCE_ORB(ENTITY),
EYE_OF_ENDER(ENTITY),
FALLING_BLOCK(ENTITY),
ITEM(ENTITY),
TNT(ENTITY),
OMINOUS_ITEM_SPAWNER(ENTITY),
MARKER(ENTITY),
LIGHTNING_BOLT(ENTITY),
INTERACTION(ENTITY),
DISPLAY(ENTITY, null),
BLOCK_DISPLAY(DISPLAY),
ITEM_DISPLAY(DISPLAY),
TEXT_DISPLAY(DISPLAY),
// Hanging entities
HANGING_ENTITY(ENTITY, null),
LEASH_KNOT(HANGING_ENTITY),
PAINTING(HANGING_ENTITY),
ITEM_FRAME(HANGING_ENTITY),
GLOW_ITEM_FRAME(ITEM_FRAME),
// Projectiles
PROJECTILE(ENTITY, null),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
POTION(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
FISHING_BOBBER(PROJECTILE),
WITHER_SKULL(PROJECTILE),
DRAGON_FIREBALL(PROJECTILE), // Doesn't actually inherit fireball
ABSTRACT_ARROW(PROJECTILE, null),
ARROW(ABSTRACT_ARROW),
SPECTRAL_ARROW(ABSTRACT_ARROW),
TRIDENT(ABSTRACT_ARROW),
ABSTRACT_FIREBALL(ENTITY, null),
FIREBALL(ABSTRACT_FIREBALL),
SMALL_FIREBALL(ABSTRACT_FIREBALL),
ABSTRACT_WIND_CHARGE(PROJECTILE, null),
WIND_CHARGE(ABSTRACT_WIND_CHARGE),
BREEZE_WIND_CHARGE(ABSTRACT_WIND_CHARGE),
// Vehicles
VEHICLE(ENTITY, null),
ABSTRACT_MINECART(VEHICLE, null),
MINECART(ABSTRACT_MINECART),
FURNACE_MINECART(ABSTRACT_MINECART),
COMMAND_BLOCK_MINECART(ABSTRACT_MINECART),
TNT_MINECART(ABSTRACT_MINECART),
SPAWNER_MINECART(ABSTRACT_MINECART),
ABSTRACT_MINECART_CONTAINER(ABSTRACT_MINECART, null),
CHEST_MINECART(ABSTRACT_MINECART_CONTAINER),
HOPPER_MINECART(ABSTRACT_MINECART_CONTAINER),
ABSTRACT_BOAT(VEHICLE, null),
ABSTRACT_CHEST_BOAT(ABSTRACT_BOAT, null),
ACACIA_BOAT(ABSTRACT_BOAT),
ACACIA_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
BAMBOO_CHEST_RAFT(ABSTRACT_CHEST_BOAT),
BAMBOO_RAFT(ABSTRACT_BOAT),
BIRCH_BOAT(ABSTRACT_BOAT),
BIRCH_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
CHERRY_BOAT(ABSTRACT_BOAT),
CHERRY_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
DARK_OAK_BOAT(ABSTRACT_BOAT),
DARK_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
JUNGLE_BOAT(ABSTRACT_BOAT),
JUNGLE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
MANGROVE_BOAT(ABSTRACT_BOAT),
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),
// Living entities as a larger subclass
LIVING_ENTITY(ENTITY, null),
ARMOR_STAND(LIVING_ENTITY),
PLAYER(LIVING_ENTITY),
// Mobs as a larger subclass
MOB(LIVING_ENTITY, null),
ENDER_DRAGON(MOB),
SLIME(MOB),
MAGMA_CUBE(SLIME),
// Ambient mobs
AMBIENT_CREATURE(MOB, null),
BAT(AMBIENT_CREATURE),
// Flying mobs
FLYING_MOB(MOB, null),
GHAST(FLYING_MOB),
PHANTOM(FLYING_MOB),
// Pathfinder mobs and its subclasses
PATHFINDER_MOB(MOB, null),
ALLAY(PATHFINDER_MOB),
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
SNOW_GOLEM(ABSTRACT_GOLEM),
IRON_GOLEM(ABSTRACT_GOLEM),
SHULKER(ABSTRACT_GOLEM),
// Ageable mobs and (tamable) animals
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
VILLAGER(ABSTRACT_VILLAGER),
WANDERING_TRADER(ABSTRACT_VILLAGER),
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
AXOLOTL(ABSTRACT_ANIMAL),
CHICKEN(ABSTRACT_ANIMAL),
PANDA(ABSTRACT_ANIMAL),
PIG(ABSTRACT_ANIMAL),
POLAR_BEAR(ABSTRACT_ANIMAL),
RABBIT(ABSTRACT_ANIMAL),
SHEEP(ABSTRACT_ANIMAL),
BEE(ABSTRACT_ANIMAL),
TURTLE(ABSTRACT_ANIMAL),
FOX(ABSTRACT_ANIMAL),
FROG(ABSTRACT_ANIMAL),
GOAT(ABSTRACT_ANIMAL),
HOGLIN(ABSTRACT_ANIMAL),
STRIDER(ABSTRACT_ANIMAL),
SNIFFER(ABSTRACT_ANIMAL),
ARMADILLO(ABSTRACT_ANIMAL),
COW(ABSTRACT_ANIMAL),
MOOSHROOM(COW),
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
CAT(TAMABLE_ANIMAL),
OCELOT(TAMABLE_ANIMAL),
WOLF(TAMABLE_ANIMAL),
PARROT(TAMABLE_ANIMAL),
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
HORSE(ABSTRACT_HORSE),
SKELETON_HORSE(ABSTRACT_HORSE),
ZOMBIE_HORSE(ABSTRACT_HORSE),
CAMEL(ABSTRACT_HORSE),
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
DONKEY(ABSTRACT_CHESTED_HORSE),
MULE(ABSTRACT_CHESTED_HORSE),
LLAMA(ABSTRACT_CHESTED_HORSE),
TRADER_LLAMA(LLAMA),
// Monsters
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
BLAZE(ABSTRACT_MONSTER),
CREEPER(ABSTRACT_MONSTER),
ENDERMITE(ABSTRACT_MONSTER),
ENDERMAN(ABSTRACT_MONSTER),
GIANT(ABSTRACT_MONSTER),
SILVERFISH(ABSTRACT_MONSTER),
VEX(ABSTRACT_MONSTER),
WITHER(ABSTRACT_MONSTER),
BREEZE(ABSTRACT_MONSTER),
ZOGLIN(ABSTRACT_MONSTER),
WARDEN(ABSTRACT_MONSTER),
CREAKING(ABSTRACT_MONSTER),
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
SKELETON(ABSTRACT_SKELETON),
STRAY(ABSTRACT_SKELETON),
WITHER_SKELETON(ABSTRACT_SKELETON),
BOGGED(ABSTRACT_SKELETON),
ZOMBIE(ABSTRACT_MONSTER),
DROWNED(ZOMBIE),
HUSK(ZOMBIE),
ZOMBIFIED_PIGLIN(ZOMBIE),
ZOMBIE_VILLAGER(ZOMBIE),
GUARDIAN(ABSTRACT_MONSTER),
ELDER_GUARDIAN(GUARDIAN),
SPIDER(ABSTRACT_MONSTER),
CAVE_SPIDER(SPIDER),
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
PIGLIN(ABSTRACT_PIGLIN),
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
// Water mobs
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
DOLPHIN(AGEABLE_WATER_CREATURE),
SQUID(AGEABLE_WATER_CREATURE),
GLOW_SQUID(SQUID),
WATER_ANIMAL(PATHFINDER_MOB, null),
ABSTRACT_FISH(WATER_ANIMAL, null),
PUFFERFISH(ABSTRACT_FISH),
TADPOLE(ABSTRACT_FISH),
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
COD(ABSTRACT_SCHOOLING_FISH),
SALMON(ABSTRACT_SCHOOLING_FISH),
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
// Raiders
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
WITCH(ABSTRACT_RAIDER),
RAVAGER(ABSTRACT_RAIDER),
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
VINDICATOR(ABSTRACT_ILLAGER),
PILLAGER(ABSTRACT_ILLAGER),
EVOKER(SPELLCASTER_ILLAGER),
ILLUSIONER(SPELLCASTER_ILLAGER);
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
private final EntityType parent;
private final String identifier;
private int id = -1;
EntityTypes1_21_4(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes1_21_4(final EntityType parent, @Nullable final String identifier) {
this.parent = parent;
this.identifier = identifier;
}
@Override
public int getId() {
if (id == -1) {
throw new IllegalStateException("Ids have not been initialized yet (type " + name() + ")");
}
return id;
}
@Override
public String identifier() {
Preconditions.checkArgument(identifier != null, "Called identifier method on abstract type");
return identifier;
}
@Override
public @Nullable EntityType getParent() {
return parent;
}
@Override
public boolean isAbstractType() {
return identifier == null;
}
public static EntityType getTypeFromId(final int typeId) {
return EntityTypeUtil.getTypeFromId(TYPES, typeId, ENTITY);
}
public static void initialize(final Protocol<?, ?, ?, ?> protocol) {
EntityTypeUtil.initialize(values(), TYPES, protocol, (type, id) -> type.id = id);
}
}

Datei anzeigen

@ -26,10 +26,11 @@ 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.minecraft.item.Item;
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.ParticleType;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
@ -40,7 +41,7 @@ public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
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 itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
public final EntityDataType blockPositionType = add(10, Types.BLOCK_POSITION1_14);
@ -59,14 +60,15 @@ public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
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 paintingVariantType = add(26, PaintingVariant.TYPE1_21);
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) {
public EntityDataTypes1_21(final Type<Item> itemType, final ParticleType particleType, final ArrayType<Particle> particlesType) {
super(31);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
}

Datei anzeigen

@ -0,0 +1,74 @@
/*
* 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.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
public final class EntityDataTypes1_21_2 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;
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.TYPE1_21_2);
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_2(final Type<Item> itemType, final ParticleType particleType, final Type<Particle[]> particlesType) {
super(31);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
}
}

Datei anzeigen

@ -29,10 +29,10 @@ import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern, boolean showInTooltip) {
public static final Type<ArmorTrim> TYPE = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim> TYPE1_20_5 = new Type<>(ArmorTrim.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE.read(buffer);
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_20_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
@ -40,7 +40,39 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE.write(buffer, value.material);
ArmorTrimMaterial.TYPE1_20_5.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_2 = new Type<>(ArmorTrim.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_2.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_2.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_4 = new Type<>(ArmorTrim.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_4.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_4.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}

Datei anzeigen

@ -27,13 +27,19 @@ 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;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.util.Map;
public record ArmorTrimMaterial(String assetName, int itemId, float itemModelIndex,
Int2ObjectMap<String> overrideArmorMaterials, Tag description) {
Map<String, String> overrideArmorMaterials, Tag description) {
public static final HolderType<ArmorTrimMaterial> TYPE = new HolderType<>() {
public ArmorTrimMaterial(final String assetName, final int itemId, final Map<String, String> overrideArmorMaterials, final Tag description) {
this(assetName, itemId, 0F, overrideArmorMaterials, description);
}
public static final HolderType<ArmorTrimMaterial> TYPE1_20_5 = new HolderType<>() {
// The override key is an int, but given we don't use it at all and that creating a new type is annoying,
// we'll just store it in the string map:tm:
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
@ -41,10 +47,45 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Int2ObjectMap<String> overrideArmorMaterials = new Int2ObjectOpenHashMap<>(overrideArmorMaterialsSize);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final int key = Types.VAR_INT.readPrimitive(buffer);
final String value = Types.STRING.read(buffer);
overrideArmorMaterials.put(Integer.toString(key), value);
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, itemModelIndex, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
buffer.writeFloat(value.itemModelIndex());
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
Types.VAR_INT.writePrimitive(buffer, Integer.parseInt(entry.getKey()));
Types.STRING.write(buffer, entry.getValue());
}
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_2 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
overrideArmorMaterials.put(key, value);
}
@ -59,8 +100,41 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
buffer.writeFloat(value.itemModelIndex());
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
for (final Int2ObjectMap.Entry<String> entry : value.overrideArmorMaterials().int2ObjectEntrySet()) {
Types.VAR_INT.writePrimitive(buffer, entry.getIntKey());
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
Types.STRING.write(buffer, entry.getKey());
Types.STRING.write(buffer, entry.getValue());
}
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_4 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
overrideArmorMaterials.put(key, value);
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
Types.STRING.write(buffer, entry.getKey());
Types.STRING.write(buffer, entry.getValue());
}

Datei anzeigen

@ -0,0 +1,111 @@
/*
* 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.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.ArrayType;
import io.netty.buffer.ByteBuf;
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
boolean hasConsumeParticles, ConsumeEffect<?>[] consumeEffects) {
public static final Type<?>[] EFFECT_TYPES = {
ApplyStatusEffects.TYPE,
Types.HOLDER_SET, // remove effects
Types.EMPTY, // clear all effects
Types.FLOAT, // teleport randomly
Types.SOUND_EVENT // play sound
};
public static final Type<Consumable1_21_2> TYPE = new Type<>(Consumable1_21_2.class) {
@Override
public Consumable1_21_2 read(final ByteBuf buffer) {
final float consumeSeconds = buffer.readFloat();
final int animationType = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
final boolean hasConsumeParticles = buffer.readBoolean();
final ConsumeEffect<?>[] consumeEffects = ConsumeEffect.ARRAY_TYPE.read(buffer);
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, consumeEffects);
}
@Override
public void write(final ByteBuf buffer, final Consumable1_21_2 value) {
buffer.writeFloat(value.consumeSeconds);
Types.VAR_INT.writePrimitive(buffer, value.animationType);
Types.SOUND_EVENT.write(buffer, value.sound);
buffer.writeBoolean(value.hasConsumeParticles);
ConsumeEffect.ARRAY_TYPE.write(buffer, value.consumeEffects);
}
};
public record ConsumeEffect<T>(int id, Type<T> type, T value) {
public static final Type<ConsumeEffect<?>> TYPE = new Type<>(ConsumeEffect.class) {
@Override
public ConsumeEffect<?> read(final ByteBuf buffer) {
// Oh no...
final int effectType = Types.VAR_INT.readPrimitive(buffer);
final Type<?> type = EFFECT_TYPES[effectType];
final Object value = type.read(buffer);
return ConsumeEffect.of(effectType, type, value);
}
@Override
public void write(final ByteBuf buffer, final ConsumeEffect<?> value) {
Types.VAR_INT.writePrimitive(buffer, value.id);
value.writeValue(buffer);
}
};
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE = new ArrayType<>(TYPE);
static <T> ConsumeEffect<T> of(final int id, final Type<T> type, final Object value) {
//noinspection unchecked
return new ConsumeEffect<>(id, type, (T) value);
}
void writeValue(final ByteBuf buf) {
this.type.write(buf, this.value);
}
}
public record ApplyStatusEffects(PotionEffect[] effects, float probability) {
public static final Type<ApplyStatusEffects> TYPE = new Type<>(ApplyStatusEffects.class) {
@Override
public ApplyStatusEffects read(final ByteBuf buffer) {
final PotionEffect[] effects = PotionEffect.ARRAY_TYPE.read(buffer);
final float probability = buffer.readFloat();
return new ApplyStatusEffects(effects, probability);
}
@Override
public void write(final ByteBuf buffer, final ApplyStatusEffects value) {
PotionEffect.ARRAY_TYPE.write(buffer, value.effects);
buffer.writeFloat(value.probability);
}
};
}
}

Datei anzeigen

@ -0,0 +1,49 @@
/*
* 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 io.netty.buffer.ByteBuf;
public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[] strings, int[] colors) {
public static final Type<CustomModelData1_21_4> TYPE = new Type<>(CustomModelData1_21_4.class) {
@Override
public CustomModelData1_21_4 read(final ByteBuf buffer) {
final float[] floats = Types.FLOAT_ARRAY_PRIMITIVE.read(buffer);
final boolean[] booleans = Types.BOOLEAN_ARRAY_PRIMITIVE.read(buffer);
final String[] strings = Types.STRING_ARRAY.read(buffer);
final int[] colors = Types.INT_ARRAY_PRIMITIVE.read(buffer);
return new CustomModelData1_21_4(floats, booleans, strings, colors);
}
@Override
public void write(final ByteBuf buffer, final CustomModelData1_21_4 value) {
Types.FLOAT_ARRAY_PRIMITIVE.write(buffer, value.floats());
Types.BOOLEAN_ARRAY_PRIMITIVE.write(buffer, value.booleans());
Types.STRING_ARRAY.write(buffer, value.strings());
Types.INT_ARRAY_PRIMITIVE.write(buffer, value.colors());
}
};
}

Datei anzeigen

@ -0,0 +1,43 @@
/*
* 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 io.netty.buffer.ByteBuf;
public record DamageResistant(String typesTagKey) {
public static final Type<DamageResistant> TYPE = new Type<>(DamageResistant.class) {
@Override
public DamageResistant read(final ByteBuf buffer) {
final String typesTagKey = Types.STRING.read(buffer);
return new DamageResistant(typesTagKey);
}
@Override
public void write(final ByteBuf buffer, final DamageResistant value) {
Types.STRING.write(buffer, value.typesTagKey());
}
};
}

Datei anzeigen

@ -22,26 +22,23 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2.ConsumeEffect;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record FoodEffect(PotionEffect effect, float probability) {
public record DeathProtection(ConsumeEffect<?>[] deathEffects) {
public static final Type<FoodEffect> TYPE = new Type<>(FoodEffect.class) {
public static final Type<DeathProtection> TYPE = new Type<>(DeathProtection.class) {
@Override
public FoodEffect read(final ByteBuf buffer) {
final PotionEffect effect = PotionEffect.TYPE.read(buffer);
final float probability = buffer.readFloat();
return new FoodEffect(effect, probability);
public DeathProtection read(final ByteBuf buffer) {
final ConsumeEffect<?>[] deathEffects = ConsumeEffect.ARRAY_TYPE.read(buffer);
return new DeathProtection(deathEffects);
}
@Override
public void write(final ByteBuf buffer, final FoodEffect value) {
PotionEffect.TYPE.write(buffer, value.effect);
buffer.writeFloat(value.probability);
public void write(final ByteBuf buffer, final DeathProtection value) {
ConsumeEffect.ARRAY_TYPE.write(buffer, value.deathEffects);
}
};
public static final Type<FoodEffect[]> ARRAY_TYPE = new ArrayType<>(TYPE);
}

Datei anzeigen

@ -0,0 +1,69 @@
/*
* 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.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
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;
import org.checkerframework.checker.nullness.qual.Nullable;
public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Nullable String model,
@Nullable String cameraOverlay, @Nullable HolderSet allowedEntities, boolean dispensable,
boolean swappable, boolean damageOnHurt) {
public static final Type<Equippable> TYPE = new Type<>(Equippable.class) {
@Override
public Equippable read(final ByteBuf buffer) {
final int equipmentSlot = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final String model = Types.OPTIONAL_STRING.read(buffer);
final String cameraOverlay = Types.OPTIONAL_STRING.read(buffer);
final HolderSet allowedEntities = Types.OPTIONAL_HOLDER_SET.read(buffer);
final boolean dispensable = buffer.readBoolean();
final boolean swappable = buffer.readBoolean();
final boolean damageOnHurt = buffer.readBoolean();
return new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
}
@Override
public void write(final ByteBuf buffer, final Equippable value) {
Types.VAR_INT.writePrimitive(buffer, value.equipmentSlot());
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.OPTIONAL_STRING.write(buffer, value.model());
Types.OPTIONAL_STRING.write(buffer, value.cameraOverlay());
Types.OPTIONAL_HOLDER_SET.write(buffer, value.allowedEntities());
buffer.writeBoolean(value.dispensable());
buffer.writeBoolean(value.swappable());
buffer.writeBoolean(value.damageOnHurt());
}
};
public Equippable rewrite(final Int2IntFunction soundIdRewriter) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriter);
return soundEvent == this.soundEvent ? this : new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
}
}

Datei anzeigen

@ -25,25 +25,27 @@ 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.ArrayType;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record FoodProperties(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
Item usingConvertsTo, FoodEffect[] possibleEffects) {
public record FoodProperties1_20_5(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
@Nullable Item usingConvertsTo, FoodEffect[] possibleEffects) {
public static final Type<FoodProperties> TYPE1_20_5 = new Type<>(FoodProperties.class) {
public static final Type<FoodProperties1_20_5> TYPE1_20_5 = new Type<>(FoodProperties1_20_5.class) {
@Override
public FoodProperties read(final ByteBuf buffer) {
public FoodProperties1_20_5 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 FoodEffect[] possibleEffects = FoodEffect.ARRAY_TYPE.read(buffer);
return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, null, possibleEffects);
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, null, possibleEffects);
}
@Override
public void write(final ByteBuf buffer, final FoodProperties value) {
public void write(final ByteBuf buffer, final FoodProperties1_20_5 value) {
Types.VAR_INT.writePrimitive(buffer, value.nutrition);
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
@ -51,20 +53,20 @@ 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) {
public static final Type<FoodProperties1_20_5> TYPE1_21 = new Type<>(FoodProperties1_20_5.class) {
@Override
public FoodProperties read(final ByteBuf buffer) {
public FoodProperties1_20_5 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);
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo, possibleEffects);
}
@Override
public void write(final ByteBuf buffer, final FoodProperties value) {
public void write(final ByteBuf buffer, final FoodProperties1_20_5 value) {
Types.VAR_INT.writePrimitive(buffer, value.nutrition);
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
@ -73,4 +75,23 @@ public record FoodProperties(int nutrition, float saturationModifier, boolean ca
FoodEffect.ARRAY_TYPE.write(buffer, value.possibleEffects);
}
};
public record FoodEffect(PotionEffect effect, float probability) {
public static final Type<FoodEffect> TYPE = new Type<>(FoodEffect.class) {
@Override
public FoodEffect read(final ByteBuf buffer) {
final PotionEffect effect = PotionEffect.TYPE.read(buffer);
final float probability = buffer.readFloat();
return new FoodEffect(effect, probability);
}
@Override
public void write(final ByteBuf buffer, final FoodEffect value) {
PotionEffect.TYPE.write(buffer, value.effect);
buffer.writeFloat(value.probability);
}
};
public static final Type<FoodEffect[]> ARRAY_TYPE = new ArrayType<>(TYPE);
}
}

Datei anzeigen

@ -0,0 +1,47 @@
/*
* 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 io.netty.buffer.ByteBuf;
public record FoodProperties1_21_2(int nutrition, float saturationModifier, boolean canAlwaysEat) {
public static final Type<FoodProperties1_21_2> TYPE = new Type<>(FoodProperties1_21_2.class) {
@Override
public FoodProperties1_21_2 read(final ByteBuf buffer) {
final int nutrition = Types.VAR_INT.readPrimitive(buffer);
final float saturationModifier = buffer.readFloat();
final boolean canAlwaysEat = buffer.readBoolean();
return new FoodProperties1_21_2(nutrition, saturationModifier, canAlwaysEat);
}
@Override
public void write(final ByteBuf buffer, final FoodProperties1_21_2 value) {
Types.VAR_INT.writePrimitive(buffer, value.nutrition);
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
}
};
}

Datei anzeigen

@ -29,27 +29,27 @@ import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Instrument(Holder<SoundEvent> soundEvent, int useDuration, float range) {
public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, float range) {
public static final HolderType<Instrument> TYPE = new HolderType<>() {
public static final HolderType<Instrument1_20_5> TYPE = new HolderType<>() {
@Override
public Instrument readDirect(final ByteBuf buffer) {
public Instrument1_20_5 readDirect(final ByteBuf buffer) {
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final int useDuration = Types.VAR_INT.readPrimitive(buffer);
final float range = buffer.readFloat();
return new Instrument(soundEvent, useDuration, range);
final float range = Types.FLOAT.readPrimitive(buffer);
return new Instrument1_20_5(soundEvent, useDuration, range);
}
@Override
public void writeDirect(final ByteBuf buffer, final Instrument value) {
public void writeDirect(final ByteBuf buffer, final Instrument1_20_5 value) {
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.VAR_INT.writePrimitive(buffer, value.useDuration());
buffer.writeFloat(value.range());
Types.FLOAT.writePrimitive(buffer, value.range());
}
};
public Instrument rewrite(final Int2IntFunction soundIdRewriteFunction) {
public Instrument1_20_5 rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
return soundEvent == this.soundEvent ? this : new Instrument(soundEvent, useDuration, range);
return soundEvent == this.soundEvent ? this : new Instrument1_20_5(soundEvent, useDuration, range);
}
}

Datei anzeigen

@ -0,0 +1,58 @@
/*
* 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.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range, Tag description) {
public static final HolderType<Instrument1_21_2> TYPE = new HolderType<>() {
@Override
public Instrument1_21_2 readDirect(final ByteBuf buffer) {
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final float useDuration = Types.FLOAT.readPrimitive(buffer);
final float range = Types.FLOAT.readPrimitive(buffer);
final Tag description = Types.TAG.read(buffer);
return new Instrument1_21_2(soundEvent, useDuration, range, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final Instrument1_21_2 value) {
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.FLOAT.writePrimitive(buffer, value.useDuration());
Types.FLOAT.writePrimitive(buffer, value.range());
Types.TAG.write(buffer, value.description());
}
};
public Instrument1_21_2 rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, description);
}
}

Datei anzeigen

@ -27,15 +27,20 @@ import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record PotionContents(@Nullable Integer potion, @Nullable Integer customColor, PotionEffect[] customEffects) {
public record PotionContents(@Nullable Integer potion, @Nullable Integer customColor, PotionEffect[] customEffects,
@Nullable String customName) {
public static final Type<PotionContents> TYPE = new Type<>(PotionContents.class) {
public PotionContents(final @Nullable Integer potion, final @Nullable Integer customColor, final PotionEffect[] customEffects) {
this(potion, customColor, customEffects, null);
}
public static final Type<PotionContents> TYPE1_20_5 = new Type<>(PotionContents.class) {
@Override
public PotionContents read(final ByteBuf buffer) {
final Integer potion = buffer.readBoolean() ? Types.VAR_INT.readPrimitive(buffer) : null;
final Integer customColor = buffer.readBoolean() ? buffer.readInt() : null;
final PotionEffect[] customEffects = PotionEffect.ARRAY_TYPE.read(buffer);
return new PotionContents(potion, customColor, customEffects);
return new PotionContents(potion, customColor, customEffects, null);
}
@Override
@ -53,4 +58,31 @@ public record PotionContents(@Nullable Integer potion, @Nullable Integer customC
PotionEffect.ARRAY_TYPE.write(buffer, value.customEffects);
}
};
public static final Type<PotionContents> TYPE1_21_2 = new Type<>(PotionContents.class) {
@Override
public PotionContents read(final ByteBuf buffer) {
final Integer potion = buffer.readBoolean() ? Types.VAR_INT.readPrimitive(buffer) : null;
final Integer customColor = buffer.readBoolean() ? buffer.readInt() : null;
final PotionEffect[] customEffects = PotionEffect.ARRAY_TYPE.read(buffer);
final String customName = Types.OPTIONAL_STRING.read(buffer);
return new PotionContents(potion, customColor, customEffects, customName);
}
@Override
public void write(final ByteBuf buffer, final PotionContents value) {
buffer.writeBoolean(value.potion != null);
if (value.potion != null) {
Types.VAR_INT.writePrimitive(buffer, value.potion);
}
buffer.writeBoolean(value.customColor != null);
if (value.customColor != null) {
buffer.writeInt(value.customColor);
}
PotionEffect.ARRAY_TYPE.write(buffer, value.customEffects);
Types.OPTIONAL_STRING.write(buffer, value.customName);
}
};
}

Datei anzeigen

@ -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.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public record UseCooldown(float seconds, @Nullable String cooldownGroup) {
public static final Type<UseCooldown> TYPE = new Type<>(UseCooldown.class) {
@Override
public UseCooldown read(final ByteBuf buffer) {
final float seconds = buffer.readFloat();
final String cooldownGroup = Types.OPTIONAL_STRING.read(buffer);
return new UseCooldown(seconds, cooldownGroup);
}
@Override
public void write(final ByteBuf buffer, final UseCooldown value) {
buffer.writeFloat(value.seconds());
Types.OPTIONAL_STRING.write(buffer, value.cooldownGroup());
}
};
public UseCooldown rewrite(final Function<String, String> idRewriter) {
if (cooldownGroup == null) {
return this;
}
final String mappedCooldownGroup = idRewriter.apply(cooldownGroup);
return new UseCooldown(seconds, mappedCooldownGroup);
}
}

Datei anzeigen

@ -198,6 +198,14 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
}
}
public void registerFinishConfiguration(final CU packetType, final PacketHandler handler) {
registerClientbound(packetType, wrapper -> {
// TODO Temporary solution to handle the finish configuration packet already having changed our tracked protocol state in a previous handler
wrapper.user().getProtocolInfo().setServerState(State.CONFIGURATION);
handler.handle(wrapper);
});
}
@Override
public final void loadMappingData() {
getMappingData().load();

Datei anzeigen

@ -36,6 +36,7 @@ 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.ParticleRewriter;
import com.viaversion.viaversion.api.rewriter.TagRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.exception.CancelException;
@ -374,6 +375,15 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
return null;
}
/**
* Returns the protocol's particle rewriter if present.
*
* @return particle rewriter
*/
default @Nullable ParticleRewriter getParticleRewriter() {
return null;
}
/**
* Returns the protocol's tag rewriter if present.
*

Datei anzeigen

@ -43,7 +43,8 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
private static final List<ProtocolVersion> VERSION_LIST = new ArrayList<>();
public static final ProtocolVersion v1_7_2 = register(4, "1.7.2-1.7.5", new SubVersionRange("1.7", 2, 5));
@Deprecated(forRemoval=true) public static final ProtocolVersion v1_7_1 = v1_7_2;
@Deprecated(forRemoval = true)
public static final ProtocolVersion v1_7_1 = v1_7_2;
public static final ProtocolVersion v1_7_6 = register(5, "1.7.6-1.7.10", new SubVersionRange("1.7", 6, 10));
public static final ProtocolVersion v1_8 = register(47, "1.8.x", new SubVersionRange("1.8", 0, 9));
public static final ProtocolVersion v1_9 = register(107, "1.9");
@ -85,8 +86,14 @@ 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, "1.21.2-1.21.3", new SubVersionRange("1.21", 2, 3));
public static final ProtocolVersion v1_21_4 = register(769, "1.21.4");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
unknown.known = false;
}
public static ProtocolVersion register(int version, String name) {
return register(version, -1, name);
}
@ -150,7 +157,11 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
return protocolVersion;
}
}
return new ProtocolVersion(VersionType.SPECIAL, version, -1, "Unknown (" + version + ")", null);
// Will be made nullable instead in the future...
final ProtocolVersion unknown = new ProtocolVersion(versionType, version, -1, "Unknown (" + version + ")", null);
unknown.known = false;
return unknown;
}
public static @NonNull ProtocolVersion getProtocol(final int version) {
@ -201,6 +212,8 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
private final int snapshotVersion;
private final String name;
private final Set<String> includedVersions;
@Deprecated // Remove when getProtocol is made nullable
private boolean known = true;
/**
* Constructs a new ProtocolVersion instance.
@ -285,12 +298,12 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
}
/**
* Returns whether the protocol is set. Should only be unknown for unregistered protocols returned by {@link #getProtocol(int)}.
* Returns whether the protocol version is {@link #unknown}. For checking if the protocol version is registered, use {@link #isRegistered(VersionType, int)}
*
* @return true if the protocol is set
* @return true if the protocol version is unknown
*/
public boolean isKnown() {
return version != -1;
return known;
}
/**

Datei anzeigen

@ -58,6 +58,14 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
*/
int newEntityId(int id);
/**
* Returns the mapped entity (or the same if it has not changed).
*
* @param identifier unmapped entity identifier
* @return mapped entity identifier
*/
String mappedEntityIdentifier(String identifier);
/**
* Handles and transforms entity data of an entity.
*

Datei anzeigen

@ -0,0 +1,27 @@
/*
* 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.api.rewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Particle;
public interface ParticleRewriter {
void rewriteParticle(UserConnection connection, Particle particle);
}

Datei anzeigen

@ -45,12 +45,14 @@ import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.api.minecraft.ChunkPosition;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.BitSetType;
import com.viaversion.viaversion.api.type.types.BooleanArrayType;
import com.viaversion.viaversion.api.type.types.BooleanType;
import com.viaversion.viaversion.api.type.types.ByteArrayType;
import com.viaversion.viaversion.api.type.types.ByteType;
import com.viaversion.viaversion.api.type.types.ComponentType;
import com.viaversion.viaversion.api.type.types.DoubleType;
import com.viaversion.viaversion.api.type.types.EmptyType;
import com.viaversion.viaversion.api.type.types.FloatArrayType;
import com.viaversion.viaversion.api.type.types.FloatType;
import com.viaversion.viaversion.api.type.types.IntArrayType;
import com.viaversion.viaversion.api.type.types.IntType;
@ -115,14 +117,17 @@ public final class Types {
public static final Type<byte[]> OPTIONAL_BYTE_ARRAY_PRIMITIVE = new ByteArrayType.OptionalByteArrayType();
public static final Type<byte[]> SHORT_BYTE_ARRAY = new ShortByteArrayType();
public static final Type<byte[]> REMAINING_BYTES = new RemainingBytesType();
public static final Type<int[]> INT_ARRAY_PRIMITIVE = new IntArrayType();
public static final ShortType SHORT = new ShortType();
public static final UnsignedShortType UNSIGNED_SHORT = new UnsignedShortType();
public static final IntType INT = new IntType();
public static final Type<int[]> INT_ARRAY_PRIMITIVE = new IntArrayType();
public static final FloatType FLOAT = new FloatType();
public static final FloatType.OptionalFloatType OPTIONAL_FLOAT = new FloatType.OptionalFloatType();
public static final Type<float[]> FLOAT_ARRAY_PRIMITIVE = new FloatArrayType();
public static final DoubleType DOUBLE = new DoubleType();
public static final LongType LONG = new LongType();
@ -130,6 +135,7 @@ public final class Types {
public static final BooleanType BOOLEAN = new BooleanType();
public static final BooleanType.OptionalBooleanType OPTIONAL_BOOLEAN = new BooleanType.OptionalBooleanType();
public static final Type<boolean[]> BOOLEAN_ARRAY_PRIMITIVE = new BooleanArrayType();
/* Other Types */
public static final Type<JsonElement> COMPONENT = new ComponentType();
@ -149,6 +155,8 @@ public final class Types {
public static final VarLongType VAR_LONG = new VarLongType();
/* MC Types */
public static final Type<byte[]> SERVERBOUND_CUSTOM_PAYLOAD_DATA = new RemainingBytesType(Short.MAX_VALUE);
public static final Type<BlockPosition> BLOCK_POSITION1_8 = new BlockPositionType1_8();
public static final Type<BlockPosition> OPTIONAL_POSITION1_8 = new BlockPositionType1_8.OptionalBlockPositionType();
public static final Type<BlockPosition> BLOCK_POSITION1_14 = new BlockPositionType1_14();
@ -189,7 +197,10 @@ public final class Types {
public static final Type<PlayerMessageSignature> OPTIONAL_PLAYER_MESSAGE_SIGNATURE = new PlayerMessageSignatureType.OptionalPlayerMessageSignatureType();
public static final Type<PlayerMessageSignature[]> PLAYER_MESSAGE_SIGNATURE_ARRAY = new ArrayType<>(PLAYER_MESSAGE_SIGNATURE);
public static final BitSetType PROFILE_ACTIONS_ENUM = new BitSetType(6);
public static final BitSetType PROFILE_ACTIONS_ENUM1_19_3 = new BitSetType(6);
public static final BitSetType PROFILE_ACTIONS_ENUM1_21_2 = new BitSetType(7);
public static final BitSetType PROFILE_ACTIONS_ENUM1_21_4 = new BitSetType(8);
public static final ByteArrayType SIGNATURE_BYTES = new ByteArrayType(256);
public static final BitSetType ACKNOWLEDGED_BIT_SET = new BitSetType(20);
public static final ByteArrayType.OptionalByteArrayType OPTIONAL_SIGNATURE_BYTES = new ByteArrayType.OptionalByteArrayType(256);

Datei anzeigen

@ -26,13 +26,22 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
public class ArrayType<T> extends Type<T[]> {
private final Type<T> elementType;
private final int maxLength;
public ArrayType(Type<T> type) {
this(type, -1);
}
public ArrayType(Type<T> type, int maxLength) {
//noinspection unchecked
super(type.getTypeName() + " Array", (Class<T[]>) getArrayClass(type.getOutputClass()));
this.elementType = type;
this.maxLength = maxLength;
}
public static Class<?> getArrayClass(Class<?> componentType) {
@ -43,16 +52,40 @@ public class ArrayType<T> extends Type<T[]> {
@Override
public T[] read(ByteBuf buffer) {
int amount = Types.VAR_INT.readPrimitive(buffer);
T[] array = (T[]) Array.newInstance(elementType.getOutputClass(), amount);
if (maxLength != -1 && amount > maxLength) {
throw new IllegalArgumentException("Array length " + amount + " is longer than maximum " + maxLength);
}
for (int i = 0; i < amount; i++) {
return amount < Short.MAX_VALUE ? readArray(buffer, amount) : readList(buffer, amount);
}
private T[] readArray(ByteBuf buffer, int length) {
T[] array = createArray(length);
for (int i = 0; i < length; i++) {
array[i] = elementType.read(buffer);
}
return array;
}
private T[] readList(ByteBuf buffer, int length) {
List<T> list = new ArrayList<>();
for (int i = 0; i < length; i++) {
list.add(elementType.read(buffer));
}
return list.toArray(createArray(0));
}
private T[] createArray(int length) {
//noinspection unchecked
return (T[]) Array.newInstance(elementType.getOutputClass(), length);
}
@Override
public void write(ByteBuf buffer, T[] object) {
if (maxLength != -1 && object.length > maxLength) {
throw new IllegalArgumentException("Array length " + object.length + " is longer than maximum " + maxLength);
}
Types.VAR_INT.writePrimitive(buffer, object.length);
for (T o : object) {
elementType.write(buffer, o);

Datei anzeigen

@ -0,0 +1,67 @@
/*
* 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;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
// Ok...
public class BooleanArrayType extends Type<boolean[]> {
private final int length;
public BooleanArrayType(final int length) {
super(boolean[].class);
this.length = length;
}
public BooleanArrayType() {
super(boolean[].class);
this.length = -1;
}
@Override
public void write(final ByteBuf buffer, final boolean[] object) {
if (this.length != -1) {
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
} else {
Types.VAR_INT.writePrimitive(buffer, object.length);
}
for (final boolean b : object) {
buffer.writeBoolean(b);
}
}
@Override
public boolean[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final boolean[] array = new boolean[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readBoolean();
}
return array;
}
}

Datei anzeigen

@ -0,0 +1,66 @@
/*
* 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;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public class FloatArrayType extends Type<float[]> {
private final int length;
public FloatArrayType(final int length) {
super(float[].class);
this.length = length;
}
public FloatArrayType() {
super(float[].class);
this.length = -1;
}
@Override
public void write(final ByteBuf buffer, final float[] object) {
if (this.length != -1) {
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
} else {
Types.VAR_INT.writePrimitive(buffer, object.length);
}
for (final float f : object) {
buffer.writeFloat(f);
}
}
@Override
public float[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
final float[] array = new float[length];
for (int i = 0; i < length; i++) {
array[i] = buffer.readFloat();
}
return array;
}
}

Datei anzeigen

@ -36,11 +36,19 @@ public class IntType extends Type<Integer> implements TypeConverter<Integer> {
return buffer.readInt();
}
public int readPrimitive(ByteBuf buffer) {
return buffer.readInt();
}
@Override
public void write(ByteBuf buffer, Integer object) {
buffer.writeInt(object);
}
public void writePrimitive(ByteBuf buffer, int object) {
buffer.writeInt(object);
}
@Override
public Integer from(Object o) {
if (o instanceof Number number) {

Datei anzeigen

@ -26,19 +26,35 @@ import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class RemainingBytesType extends Type<byte[]> {
private final int maxLength;
public RemainingBytesType() {
this(-1);
}
public RemainingBytesType(final int maxLength) {
super(byte[].class);
this.maxLength = maxLength;
}
@Override
public byte[] read(ByteBuf buffer) {
byte[] array = new byte[buffer.readableBytes()];
public byte[] read(final ByteBuf buffer) {
final int bytes = buffer.readableBytes();
if (maxLength != -1 && bytes > maxLength) {
throw new RuntimeException("Remaining bytes cannot be longer than " + maxLength + " (got " + bytes + ")");
}
final byte[] array = new byte[bytes];
buffer.readBytes(array);
return array;
}
@Override
public void write(ByteBuf buffer, byte[] object) {
public void write(final ByteBuf buffer, final byte[] object) {
if (maxLength != -1 && object.length > maxLength) {
throw new RuntimeException("Remaining bytes cannot be longer than " + maxLength + " (got " + object.length + ")");
}
buffer.writeBytes(object);
}
}

Datei anzeigen

@ -32,6 +32,15 @@ public class VarIntType extends Type<Integer> implements TypeConverter<Integer>
private static final int VALUE_BITS = 0x7F;
private static final int MULTI_BYTE_BITS = ~VALUE_BITS;
private static final int MAX_BYTES = 5;
private static final int[] VAR_INT_LENGTHS = new int[65];
static {
// Copied from Velocity https://github.com/PaperMC/Velocity/blob/08a42b3723633ea5eb6b96c0bb42180f3c2b07eb/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java#L166
for (int i = 0; i <= 32; ++i) {
VAR_INT_LENGTHS[i] = (int) Math.ceil((31d - (i - 1)) / 7d);
}
VAR_INT_LENGTHS[32] = 1; // Special case for the number 0.
}
public VarIntType() {
super("VarInt", Integer.class);
@ -88,4 +97,8 @@ public class VarIntType extends Type<Integer> implements TypeConverter<Integer>
}
throw new UnsupportedOperationException();
}
}
public static int varIntLength(final int value) {
return VAR_INT_LENGTHS[Integer.numberOfLeadingZeros(value)];
}
}

Datei anzeigen

@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
@ -54,4 +55,14 @@ public final class ChunkSectionType1_18 extends Type<ChunkSection> {
blockPaletteType.write(buffer, section.palette(PaletteType.BLOCKS));
biomePaletteType.write(buffer, section.palette(PaletteType.BIOMES));
}
public int serializedSize(final Chunk chunk) {
int length = 0;
for (final ChunkSection section : chunk.getSections()) {
length += Short.BYTES
+ blockPaletteType.serializedSize(section.palette(PaletteType.BLOCKS))
+ biomePaletteType.serializedSize(section.palette(PaletteType.BIOMES));
}
return length;
}
}

Datei anzeigen

@ -52,14 +52,10 @@ public final class ChunkType1_18 extends Type<Chunk> {
final CompoundTag heightMap = Types.NAMED_COMPOUND_TAG.read(buffer);
// Read sections
final ByteBuf sectionsBuf = buffer.readBytes(Types.VAR_INT.readPrimitive(buffer));
final ByteBuf sectionsBuf = buffer.readSlice(Types.VAR_INT.readPrimitive(buffer));
final ChunkSection[] sections = new ChunkSection[ySectionCount];
try {
for (int i = 0; i < ySectionCount; i++) {
sections[i] = sectionType.read(sectionsBuf);
}
} finally {
sectionsBuf.release();
for (int i = 0; i < ySectionCount; i++) {
sections[i] = sectionType.read(sectionsBuf);
}
final int blockEntitiesLength = Types.VAR_INT.readPrimitive(buffer);
@ -78,16 +74,9 @@ public final class ChunkType1_18 extends Type<Chunk> {
Types.NAMED_COMPOUND_TAG.write(buffer, chunk.getHeightMap());
final ByteBuf sectionBuffer = buffer.alloc().buffer();
try {
for (final ChunkSection section : chunk.getSections()) {
sectionType.write(sectionBuffer, section);
}
sectionBuffer.readerIndex(0);
Types.VAR_INT.writePrimitive(buffer, sectionBuffer.readableBytes());
buffer.writeBytes(sectionBuffer);
} finally {
sectionBuffer.release(); // release buffer
Types.VAR_INT.writePrimitive(buffer, sectionType.serializedSize(chunk));
for (final ChunkSection section : chunk.getSections()) {
sectionType.write(buffer, section);
}
Types.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());

Datei anzeigen

@ -52,14 +52,10 @@ public final class ChunkType1_20_2 extends Type<Chunk> {
final CompoundTag heightMap = Types.COMPOUND_TAG.read(buffer);
// Read sections
final ByteBuf sectionsBuf = buffer.readBytes(Types.VAR_INT.readPrimitive(buffer));
final ByteBuf sectionsBuf = buffer.readSlice(Types.VAR_INT.readPrimitive(buffer));
final ChunkSection[] sections = new ChunkSection[ySectionCount];
try {
for (int i = 0; i < ySectionCount; i++) {
sections[i] = sectionType.read(sectionsBuf);
}
} finally {
sectionsBuf.release();
for (int i = 0; i < ySectionCount; i++) {
sections[i] = sectionType.read(sectionsBuf);
}
final int blockEntitiesLength = Types.VAR_INT.readPrimitive(buffer);
@ -78,16 +74,9 @@ public final class ChunkType1_20_2 extends Type<Chunk> {
Types.COMPOUND_TAG.write(buffer, chunk.getHeightMap());
final ByteBuf sectionBuffer = buffer.alloc().buffer();
try {
for (final ChunkSection section : chunk.getSections()) {
sectionType.write(sectionBuffer, section);
}
sectionBuffer.readerIndex(0);
Types.VAR_INT.writePrimitive(buffer, sectionBuffer.readableBytes());
buffer.writeBytes(sectionBuffer);
} finally {
sectionBuffer.release(); // release buffer
Types.VAR_INT.writePrimitive(buffer, sectionType.serializedSize(chunk));
for (final ChunkSection section : chunk.getSections()) {
sectionType.write(buffer, section);
}
Types.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());

Datei anzeigen

@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.minecraft.chunks.DataPaletteImpl;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.VarIntType;
import com.viaversion.viaversion.util.CompactArrayUtil;
import com.viaversion.viaversion.util.MathUtil;
import io.netty.buffer.ByteBuf;
@ -94,13 +95,7 @@ public final class PaletteType1_18 extends Type<DataPalette> {
return;
}
// 1, 2, and 3 bit linear block palettes can't be read by the client
final int min = type == PaletteType.BLOCKS ? 4 : 1;
int bitsPerValue = Math.max(min, MathUtil.ceilLog2(size));
if (bitsPerValue > type.highestBitsPerValue()) {
bitsPerValue = globalPaletteBits;
}
final int bitsPerValue = bitsPerValue(size);
buffer.writeByte(bitsPerValue);
if (bitsPerValue != globalPaletteBits) {
@ -113,4 +108,39 @@ public final class PaletteType1_18 extends Type<DataPalette> {
Types.LONG_ARRAY_PRIMITIVE.write(buffer, CompactArrayUtil.createCompactArrayWithPadding(bitsPerValue, type.size(), bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt));
}
private int bitsPerValue(final int size) {
// 1, 2, and 3 bit linear block palettes can't be read by the client
final int min = type == PaletteType.BLOCKS ? 4 : 1;
int bitsPerValue = Math.max(min, MathUtil.ceilLog2(size));
if (bitsPerValue > type.highestBitsPerValue()) {
bitsPerValue = globalPaletteBits;
}
return bitsPerValue;
}
public int serializedSize(final DataPalette palette) {
// This is a bit of extra work, but worth it to avoid otherwise having to allocate and write to an extra buffer.
// On top of saving memory, it provides small but measurable speedup compared to writing to a separate buffer and then back
final int size = palette.size();
final int bitsPerValue = bitsPerValue(size);
int serializedTypesSize = 0;
int serializedValuesSize = 1; // At least one byte for 0 length
if (size == 1) {
serializedTypesSize = VarIntType.varIntLength(palette.idByIndex(0));
} else {
if (bitsPerValue != globalPaletteBits) {
serializedTypesSize = VarIntType.varIntLength(size);
for (int i = 0; i < size; i++) {
serializedTypesSize += VarIntType.varIntLength(palette.idByIndex(i));
}
}
final int valuesPerLong = 64 / bitsPerValue;
final int values = (type.size() + valuesPerLong - 1) / valuesPerLong;
serializedValuesSize = VarIntType.varIntLength(values) + (Long.BYTES * values);
}
return Byte.BYTES + serializedTypesSize + serializedValuesSize;
}
}

Datei anzeigen

@ -63,7 +63,7 @@ public class ItemType1_20_5 extends Type<Item> {
return new Reference2ObjectOpenHashMap<>();
}
final Map<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>();
final Map<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>(Math.min(valuesSize + markersSize, 128));
for (int i = 0; i < valuesSize; i++) {
final StructuredData<?> value = dataType.read(buffer);
final StructuredDataKey<?> key = dataType.key(value.id());

Datei anzeigen

@ -87,5 +87,12 @@ public class StructuredDataType extends Type<StructuredData<?>> {
types[id] = key;
return this;
}
public DataFiller add(final StructuredDataKey<?>... keys) {
for (final StructuredDataKey<?> key : keys) {
add(key);
}
return this;
}
}
}

Datei anzeigen

@ -29,7 +29,6 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
@ -77,6 +76,10 @@ public class ParticleType extends DynamicType<Particle> {
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Blue 0-1
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Scale 0.01-4
};
public static final DataReader<Particle> DUST1_21_2 = (buf, particle) -> {
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // RGB
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Scale 0.01-4
};
public static final DataReader<Particle> DUST_TRANSITION = (buf, particle) -> {
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Red 0-1
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Green 0-1
@ -86,6 +89,11 @@ public class ParticleType extends DynamicType<Particle> {
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Green
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Blue
};
public static final DataReader<Particle> DUST_TRANSITION1_21_2 = (buf, particle) -> {
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // From RGB
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // To RGB
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Scale 0.01-4
};
public static final DataReader<Particle> VIBRATION = (buf, particle) -> {
particle.add(Types.BLOCK_POSITION1_14, Types.BLOCK_POSITION1_14.read(buf)); // From block pos
@ -136,7 +144,22 @@ public class ParticleType extends DynamicType<Particle> {
public static final DataReader<Particle> SHRIEK = (buf, 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> COLOR = (buf, particle) -> {
particle.add(Types.INT, Types.INT.readPrimitive(buf));
};
public static final DataReader<Particle> TRAIL1_21_2 = (buf, particle) -> {
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target X
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Y
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Z
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // Color
};
public static final DataReader<Particle> TRAIL1_21_4 = (buf, particle) -> {
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target X
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Y
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Z
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // Color
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Duration
};
public static DataReader<Particle> item(Type<Item> item) {
return (buf, particle) -> particle.add(item, item.read(buf));

Datei anzeigen

@ -50,7 +50,7 @@ public final class Types1_21 {
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 EntityDataTypes1_21 ENTITY_DATA_TYPES = new EntityDataTypes1_21(ITEM, 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);
}

Datei anzeigen

@ -0,0 +1,55 @@
/*
* 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_2;
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_2 {
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[]> 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 Type<Particle[]> PARTICLES = new ArrayType<>(PARTICLE);
public static final EntityDataTypes1_21_2 ENTITY_DATA_TYPES = new EntityDataTypes1_21_2(ITEM, 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);
}

Datei anzeigen

@ -0,0 +1,55 @@
/*
* 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_4 {
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[]> 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(ITEM, 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);
}

Datei anzeigen

@ -22,11 +22,14 @@
*/
package com.viaversion.viaversion.exception;
import java.util.HashMap;
import java.util.Map;
import com.viaversion.viaversion.api.Via;
import java.util.ArrayList;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public class InformativeException extends RuntimeException {
private final Map<String, Object> info = new HashMap<>();
private static final int MAX_MESSAGE_LENGTH = 5_000;
private final List<DataEntry> dataEntries = new ArrayList<>();
private boolean shouldBePrinted = true;
private int sources;
@ -34,8 +37,8 @@ public class InformativeException extends RuntimeException {
super(cause);
}
public InformativeException set(String key, Object value) {
info.put(key, value);
public InformativeException set(String key, @Nullable Object value) {
dataEntries.add(new DataEntry(key, value));
return this;
}
@ -57,14 +60,21 @@ public class InformativeException extends RuntimeException {
@Override
public String getMessage() {
StringBuilder builder = new StringBuilder("Please report this on the Via support Discord or open an issue on the relevant GitHub repository\n");
final StringBuilder builder = new StringBuilder("Please report this on the Via support Discord or open an issue on the relevant GitHub repository\n");
boolean first = true;
for (Map.Entry<String, Object> entry : info.entrySet()) {
for (final DataEntry entry : dataEntries) {
if (!first) {
builder.append(", ");
} else {
first = false;
}
builder.append(entry.getKey()).append(": ").append(entry.getValue());
first = false;
builder.append(entry.name()).append(": ");
String s = String.valueOf(entry.value());
if (!Via.getManager().isDebug() && s.length() > 10 && builder.length() + s.length() > MAX_MESSAGE_LENGTH) {
s = s.substring(0, MAX_MESSAGE_LENGTH - builder.length()) + "...";
}
builder.append(s.replaceAll("\\s", ""));
}
return builder.toString();
}
@ -74,4 +84,7 @@ public class InformativeException extends RuntimeException {
// Don't record this stack
return this;
}
private record DataEntry(String name, @Nullable Object value) {
}
}

Datei anzeigen

@ -0,0 +1,28 @@
/*
* 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.util;
public final class Limit {
public static int max(final int value, final int max) {
if (value > max) {
throw new IllegalArgumentException("Value " + value + " is higher than the maximum " + max);
}
return value;
}
}

Datei anzeigen

@ -1,7 +1,6 @@
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.jvm.toolchain.JavaLanguageVersion
import java.io.ByteArrayOutputStream
fun Project.latestCommitHash(): String {
return runGitCommand(listOf("rev-parse", "--short", "HEAD"))
@ -16,12 +15,9 @@ fun Project.branchName(): String {
}
fun Project.runGitCommand(args: List<String>): String {
val byteOut = ByteArrayOutputStream()
exec {
return providers.exec {
commandLine = listOf("git") + args
standardOutput = byteOut
}
return byteOut.toString(Charsets.UTF_8.name()).trim()
}.standardOutput.asBytes.get().toString(Charsets.UTF_8).trim()
}
fun JavaPluginExtension.javaTarget(version: Int) {

Datei anzeigen

@ -1,5 +1,6 @@
plugins {
`java-library`
`jvm-test-suite`
}
tasks {

Datei anzeigen

@ -16,10 +16,10 @@ val main = setOf(
projects.viaversionBukkit,
projects.viaversionVelocity,
projects.viaversionFabric
).map { it.dependencyProject }
).map { it.path }
subprojects {
when (this) {
when (path) {
in main -> plugins.apply("via.shadow-conventions")
else -> plugins.apply("via.base-conventions")
}

Datei anzeigen

@ -33,6 +33,7 @@ import com.viaversion.viaversion.bukkit.platform.BukkitViaInjector;
import com.viaversion.viaversion.bukkit.platform.BukkitViaLoader;
import com.viaversion.viaversion.bukkit.platform.BukkitViaTask;
import com.viaversion.viaversion.bukkit.platform.BukkitViaTaskTask;
import com.viaversion.viaversion.bukkit.platform.FoliaViaTask;
import com.viaversion.viaversion.bukkit.platform.PaperViaInjector;
import com.viaversion.viaversion.dump.PluginInfo;
import com.viaversion.viaversion.unsupported.UnsupportedPlugin;
@ -46,6 +47,7 @@ import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.EventPriority;
@ -55,6 +57,8 @@ import org.bukkit.plugin.java.JavaPlugin;
public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player> {
private static final boolean FOLIA = PaperViaInjector.hasClass("io.papermc.paper.threadedregions.RegionizedServer");
private static final Runnable DUMMY_RUNNABLE = () -> {
};
private static ViaVersionPlugin instance;
private final BukkitCommandHandler commandHandler = new BukkitCommandHandler();
private final BukkitViaConfig conf;
@ -171,11 +175,36 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
@Override
public PlatformTask runSync(Runnable runnable, long delay) {
if (FOLIA) {
// Set the delayed tick to at least 1, as Folia requires this.
return new FoliaViaTask(getServer().getGlobalRegionScheduler().runDelayed(this, (e) -> runnable.run(), delay <= 0L ? 1L : delay));
}
return new BukkitViaTask(getServer().getScheduler().runTaskLater(this, runnable, delay));
}
public PlatformTask<?> runSyncAt(Runnable runnable, Block block) {
if (FOLIA) {
return new FoliaViaTask(getServer().getRegionScheduler().run(this, block.getLocation(), (e) -> runnable.run()));
}
return runSync(runnable);
}
public PlatformTask<?> runSyncFor(Runnable runnable, Player player) {
if (FOLIA) {
return new FoliaViaTask(player.getScheduler().run(this, (e) -> runnable.run(), DUMMY_RUNNABLE));
}
return runSync(() -> {
if (player.isOnline()) {
runnable.run();
}
});
}
@Override
public PlatformTask runRepeatingSync(Runnable runnable, long period) {
if (FOLIA) {
return new FoliaViaTask(getServer().getGlobalRegionScheduler().runAtFixedRate(this, (e) -> runnable.run(), 1, period));
}
return new BukkitViaTask(getServer().getScheduler().runTaskTimer(this, runnable, 0, period));
}

Datei anzeigen

@ -22,6 +22,7 @@ import com.viaversion.viaversion.bukkit.util.NMSUtil;
import com.viaversion.viaversion.exception.CancelCodecException;
import com.viaversion.viaversion.exception.CancelDecoderException;
import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.util.ByteBufUtil;
import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
@ -39,7 +40,7 @@ public final class BukkitDecodeHandler extends MessageToMessageDecoder<ByteBuf>
}
@Override
protected void decode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) throws Exception {
protected void decode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) {
if (!connection.checkServerboundPacket()) {
throw CancelDecoderException.generate(null);
}
@ -48,7 +49,7 @@ public final class BukkitDecodeHandler extends MessageToMessageDecoder<ByteBuf>
return;
}
final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
final ByteBuf transformedBuf = ByteBufUtil.copy(ctx.alloc(), bytebuf);
try {
connection.transformIncoming(transformedBuf, CancelDecoderException::generate);
out.add(transformedBuf.retain());

Datei anzeigen

@ -22,6 +22,7 @@ import com.viaversion.viaversion.bukkit.util.NMSUtil;
import com.viaversion.viaversion.exception.CancelCodecException;
import com.viaversion.viaversion.exception.CancelEncoderException;
import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.util.ByteBufUtil;
import com.viaversion.viaversion.util.PipelineUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
@ -52,7 +53,7 @@ public final class BukkitEncodeHandler extends MessageToMessageEncoder<ByteBuf>
return;
}
final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
final ByteBuf transformedBuf = ByteBufUtil.copy(ctx.alloc(), bytebuf);
try {
final boolean needsCompression = !handledCompression && handleCompressionOrder(ctx, transformedBuf);
connection.transformClientbound(transformedBuf, CancelEncoderException::generate);

Datei anzeigen

@ -0,0 +1,72 @@
/*
* 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.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockDamageEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
public class LegacyChangeItemListener extends PlayerChangeItemListener {
public LegacyChangeItemListener(final ViaVersionPlugin plugin) {
super(plugin);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockDamageEvent(final BlockDamageEvent event) {
final Player player = event.getPlayer();
final ItemStack item = event.getItemInHand();
sendAttributeUpdate(player, item, Slot.HAND);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onInventoryClose(final InventoryCloseEvent event) {
if (event.getPlayer() instanceof Player player &&
(event.getInventory().getType() == InventoryType.CRAFTING ||
event.getInventory().getType() == InventoryType.PLAYER)) {
sendArmorUpdate(player);
}
}
private void sendArmorUpdate(final Player player) {
final UserConnection connection = getUserConnection(player);
final EfficiencyAttributeStorage storage = getEfficiencyStorage(connection);
if (storage == null) {
return;
}
final PlayerInventory inventory = player.getInventory();
final ItemStack helmet = inventory.getHelmet();
final ItemStack leggings = swiftSneak != null ? inventory.getLeggings() : null;
final ItemStack boots = depthStrider != null ? inventory.getBoots() : null;
storage.setEnchants(player.getEntityId(), connection, storage.activeEnchants()
.aquaAffinity(helmet != null ? helmet.getEnchantmentLevel(aquaAffinity) : 0)
.swiftSneak(leggings != null ? leggings.getEnchantmentLevel(swiftSneak) : 0)
.depthStrider(boots != null ? boots.getEnchantmentLevel(depthStrider) : 0));
}
}

Datei anzeigen

@ -18,7 +18,6 @@
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;
@ -38,11 +37,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class PlayerChangeItemListener extends ViaBukkitListener {
// Use legacy function and names here to support all versions
private final Enchantment efficiency = getByName("efficiency", "DIG_SPEED");
private final Enchantment aquaAffinity = getByName("aqua_affinity", "WATER_WORKER");
private final Enchantment depthStrider = getByName("depth_strider", "DEPTH_STRIDER");
private final Enchantment soulSpeed = getByName("soul_speed", "SOUL_SPEED");
private final Enchantment swiftSneak = getByName("swift_sneak", "SWIFT_SNEAK");
protected final Enchantment efficiency = getByName("efficiency", "DIG_SPEED");
protected final Enchantment aquaAffinity = getByName("aqua_affinity", "WATER_WORKER");
protected final Enchantment depthStrider = getByName("depth_strider", "DEPTH_STRIDER");
protected final Enchantment soulSpeed = getByName("soul_speed", "SOUL_SPEED");
protected final Enchantment swiftSneak = getByName("swift_sneak", "SWIFT_SNEAK");
public PlayerChangeItemListener(final ViaVersionPlugin plugin) {
super(plugin, Protocol1_20_5To1_21.class);
@ -55,35 +54,26 @@ public class PlayerChangeItemListener extends ViaBukkitListener {
sendAttributeUpdate(player, item, Slot.HAND);
}
protected EfficiencyAttributeStorage getEfficiencyStorage(final UserConnection connection) {
return connection != null ? connection.get(EfficiencyAttributeStorage.class) : null;
}
void sendAttributeUpdate(final Player player, @Nullable final ItemStack item, final Slot slot) {
final UserConnection connection = Via.getAPI().getConnection(player.getUniqueId());
if (connection == null || !isOnPipe(player)) {
return;
}
final UserConnection connection = getUserConnection(player);
final EfficiencyAttributeStorage storage = getEfficiencyStorage(connection);
if (storage == null) return;
final EfficiencyAttributeStorage storage = connection.get(EfficiencyAttributeStorage.class);
if (storage == null) {
return;
}
final EfficiencyAttributeStorage.ActiveEnchants activeEnchants = storage.activeEnchants();
int efficiencyLevel = activeEnchants.efficiency().level();
int aquaAffinityLevel = activeEnchants.aquaAffinity().level();
int soulSpeedLevel = activeEnchants.soulSpeed().level();
int swiftSneakLevel = activeEnchants.swiftSneak().level();
int depthStriderLevel = activeEnchants.depthStrider().level();
switch (slot) {
case HAND -> efficiencyLevel = item != null ? item.getEnchantmentLevel(efficiency) : 0;
case HELMET -> aquaAffinityLevel = item != null ? item.getEnchantmentLevel(aquaAffinity) : 0;
case LEGGINGS -> swiftSneakLevel = item != null && swiftSneak != null ? item.getEnchantmentLevel(swiftSneak) : 0;
case BOOTS -> {
depthStriderLevel = item != null && depthStrider != null ? item.getEnchantmentLevel(depthStrider) : 0;
// TODO This needs continuous ticking for the supporting block as a conditional effect
// and is even more prone to desync from high ping than the other attributes
//soulSpeedLevel = item != null && soulSpeed != null ? item.getEnchantmentLevel(soulSpeed) : 0;
}
}
storage.setEnchants(player.getEntityId(), connection, efficiencyLevel, soulSpeedLevel, swiftSneakLevel, aquaAffinityLevel, depthStriderLevel);
EfficiencyAttributeStorage.ActiveEnchants enchants = storage.activeEnchants();
enchants = switch (slot) {
case HAND -> enchants.efficiency(item != null ? item.getEnchantmentLevel(efficiency) : 0);
case HELMET -> enchants.aquaAffinity(item != null ? item.getEnchantmentLevel(aquaAffinity) : 0);
case LEGGINGS -> enchants.swiftSneak(item != null && swiftSneak != null ? item.getEnchantmentLevel(swiftSneak) : 0);
case BOOTS -> enchants.depthStrider(item != null && depthStrider != null ? item.getEnchantmentLevel(depthStrider) : 0);
// TODO This needs continuous ticking for the supporting block as a conditional effect
// and is even more prone to desync from high ping than the other attributes
//soulSpeedLevel = item != null && soulSpeed != null ? item.getEnchantmentLevel(soulSpeed) : 0;
};
storage.setEnchants(player.getEntityId(), connection, enchants);
}
enum Slot {

Datei anzeigen

@ -26,23 +26,25 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.bukkit.listeners.UpdateListener;
import com.viaversion.viaversion.bukkit.listeners.multiversion.PlayerSneakListener;
import com.viaversion.viaversion.bukkit.listeners.v1_14_4to1_15.EntityToggleGlideListener;
import com.viaversion.viaversion.bukkit.listeners.v1_19_3to1_19_4.ArmorToggleListener;
import com.viaversion.viaversion.bukkit.listeners.v1_18_2to1_19.BlockBreakListener;
import com.viaversion.viaversion.bukkit.listeners.v1_19_3to1_19_4.ArmorToggleListener;
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.LegacyChangeItemListener;
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PaperPlayerChangeItemListener;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.ArmorListener;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.BlockListener;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.DeathListener;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.HandItemCache;
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.PaperPatch;
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PaperPlayerChangeItemListener;
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;
import com.viaversion.viaversion.bukkit.providers.BukkitPickItemProvider;
import com.viaversion.viaversion.bukkit.providers.BukkitViaMovementTransmitter;
import com.viaversion.viaversion.protocols.v1_11_1to1_12.provider.InventoryQuickMoveProvider;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.ConnectionData;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.providers.BlockConnectionProvider;
import com.viaversion.viaversion.protocols.v1_18_2to1_19.provider.AckSequenceProvider;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.provider.PickItemProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.HandItemProvider;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.MovementTransmitterProvider;
import java.util.HashSet;
@ -184,7 +186,12 @@ public class BukkitViaLoader implements ViaPlatformLoader {
if (PaperViaInjector.hasClass("io.papermc.paper.event.player.PlayerInventorySlotChangeEvent")) {
new PaperPlayerChangeItemListener(plugin).register();
} else {
new PlayerChangeItemListener(plugin).register();
new LegacyChangeItemListener(plugin).register();
}
}
if (serverProtocolVersion.olderThan(ProtocolVersion.v1_21_4)) {
if (PaperViaInjector.hasMethod(Material.class, "isItem")) {
Via.getManager().getProviders().use(PickItemProvider.class, new BukkitPickItemProvider(plugin));
}
}
}

Datei anzeigen

@ -0,0 +1,28 @@
/*
* 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.platform;
import com.viaversion.viaversion.api.platform.PlatformTask;
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
public record FoliaViaTask(ScheduledTask task) implements PlatformTask<ScheduledTask> {
@Override
public void cancel() {
task.cancel();
}
}

Datei anzeigen

@ -65,12 +65,7 @@ public final class PaperViaInjector {
}
private static boolean hasServerProtocolMethod() {
try {
Class.forName("org.bukkit.UnsafeValues").getDeclaredMethod("getProtocolVersion");
return true;
} catch (final ClassNotFoundException | NoSuchMethodException e) {
return false;
}
return hasMethod("org.bukkit.UnsafeValues", "getProtocolVersion");
}
private static boolean hasPaperInjectionMethod() {
@ -78,12 +73,7 @@ public final class PaperViaInjector {
}
private static boolean hasIsStoppingMethod() {
try {
Bukkit.class.getDeclaredMethod("isStopping");
return true;
} catch (final NoSuchMethodException e) {
return false;
}
return hasMethod(Bukkit.class, "isStopping");
}
private static boolean hasPacketLimiter() {
@ -98,4 +88,22 @@ public final class PaperViaInjector {
return false;
}
}
public static boolean hasMethod(final String className, final String method) {
try {
Class.forName(className).getDeclaredMethod(method);
return true;
} catch (final ClassNotFoundException | NoSuchMethodException e) {
return false;
}
}
public static boolean hasMethod(final Class<?> clazz, final String method, final Class<?>... params) {
try {
clazz.getDeclaredMethod(method, params);
return true;
} catch (final NoSuchMethodException e) {
return false;
}
}
}

Datei anzeigen

@ -84,7 +84,6 @@ public class BukkitInventoryQuickMoveProvider extends InventoryQuickMoveProvider
updateTask = new BukkitInventoryUpdateTask(this, uuid);
updateTasks.put(uuid, updateTask);
}
// http://wiki.vg/index.php?title=Protocol&oldid=13223#Click_Window
updateTask.addItem(windowId, slotId, actionId);
if (!registered && Via.getPlatform().isPluginEnabled()) {
Via.getPlatform().runSync(updateTask);

Datei anzeigen

@ -0,0 +1,184 @@
/*
* 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.providers;
import com.viaversion.viaversion.ViaVersionPlugin;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.bukkit.platform.PaperViaInjector;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.provider.PickItemProvider;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class BukkitPickItemProvider extends PickItemProvider {
private static final boolean HAS_PLACEMENT_MATERIAL_METHOD = PaperViaInjector.hasMethod("org.bukkit.block.data.BlockData", "getPlacementMaterial");
private static final boolean HAS_SPAWN_EGG_METHOD = PaperViaInjector.hasMethod(ItemFactory.class, "getSpawnEgg", EntityType.class);
private static final double BLOCK_RANGE = 4.5 + 1;
private static final double BLOCK_RANGE_SQUARED = BLOCK_RANGE * BLOCK_RANGE;
private static final double ENTITY_RANGE = 3 + 3;
private final ViaVersionPlugin plugin;
public BukkitPickItemProvider(final ViaVersionPlugin plugin) {
this.plugin = plugin;
}
@Override
public void pickItemFromBlock(final UserConnection connection, final BlockPosition blockPosition, final boolean includeData) {
final UUID uuid = connection.getProtocolInfo().getUuid();
final Player player = plugin.getServer().getPlayer(uuid);
if (player == null) {
return;
}
plugin.runSyncFor(() -> {
final Location playerLocation = player.getLocation();
if (blockPosition.distanceFromCenterSquared(playerLocation.getX(), playerLocation.getY(), playerLocation.getZ()) > BLOCK_RANGE_SQUARED) {
return;
}
final Block block = player.getWorld().getBlockAt(blockPosition.x(), blockPosition.y(), blockPosition.z());
if (block.getType() == Material.AIR) {
return;
}
final ItemStack item = blockToItem(block, includeData && player.getGameMode() == GameMode.CREATIVE);
if (item != null) {
pickItem(player, item);
}
}, player);
}
private @Nullable ItemStack blockToItem(final Block block, final boolean includeData) {
if (HAS_PLACEMENT_MATERIAL_METHOD) {
final ItemStack item = new ItemStack(block.getBlockData().getPlacementMaterial(), 1);
if (includeData && item.getItemMeta() instanceof final BlockStateMeta blockStateMeta) {
blockStateMeta.setBlockState(block.getState());
item.setItemMeta(blockStateMeta);
}
return item;
} else if (block.getType().isItem()) {
return new ItemStack(block.getType(), 1);
}
return null;
}
@Override
public void pickItemFromEntity(final UserConnection connection, final int entityId, final boolean includeData) {
if (!HAS_SPAWN_EGG_METHOD) {
return;
}
final UUID uuid = connection.getProtocolInfo().getUuid();
final Player player = plugin.getServer().getPlayer(uuid);
if (player == null) {
return;
}
plugin.runSyncFor(() -> {
final Entity entity = player.getWorld().getNearbyEntities(player.getLocation(), ENTITY_RANGE, ENTITY_RANGE, ENTITY_RANGE).stream()
.filter(e -> e.getEntityId() == entityId)
.findAny()
.orElse(null);
if (entity == null) {
return;
}
final Material spawnEggType = Bukkit.getItemFactory().getSpawnEgg(entity.getType());
if (spawnEggType != null) {
pickItem(player, new ItemStack(spawnEggType, 1));
}
}, player);
}
private void pickItem(final Player player, final ItemStack item) {
// Find matching item
final PlayerInventory inventory = player.getInventory();
final ItemStack[] contents = inventory.getStorageContents();
int sourceSlot = -1;
for (int i = 0; i < contents.length; i++) {
final ItemStack content = contents[i];
if (content == null || !content.isSimilar(item)) {
continue;
}
sourceSlot = i;
break;
}
if (sourceSlot != -1) {
moveToHotbar(inventory, sourceSlot, contents);
} else if (player.getGameMode() == GameMode.CREATIVE) {
spawnItem(item, inventory, contents);
}
}
private void spawnItem(final ItemStack item, final PlayerInventory inventory, final ItemStack[] contents) {
final int targetSlot = findEmptyHotbarSlot(inventory, inventory.getHeldItemSlot());
inventory.setHeldItemSlot(targetSlot);
final ItemStack heldItem = inventory.getItem(targetSlot);
int emptySlot = targetSlot;
if (heldItem != null && heldItem.getType() != Material.AIR) {
// Swap to the first free slot in the inventory, else add it to the current hotbar slot
for (int i = 0; i < contents.length; i++) {
if (contents[i] == null || contents[i].getType() == Material.AIR) {
emptySlot = i;
break;
}
}
}
inventory.setItem(emptySlot, heldItem);
inventory.setItemInMainHand(item);
}
private void moveToHotbar(final PlayerInventory inventory, final int sourceSlot, final ItemStack[] contents) {
if (sourceSlot < 9) {
inventory.setHeldItemSlot(sourceSlot);
return;
}
final int heldSlot = inventory.getHeldItemSlot();
final int targetSlot = findEmptyHotbarSlot(inventory, heldSlot);
inventory.setHeldItemSlot(targetSlot);
final ItemStack heldItem = inventory.getItem(targetSlot);
inventory.setItemInMainHand(contents[sourceSlot]);
inventory.setItem(sourceSlot, heldItem);
}
private int findEmptyHotbarSlot(final PlayerInventory inventory, final int heldSlot) {
for (int i = 0; i < 9; i++) {
final ItemStack item = inventory.getItem(i);
if (item == null || item.getType() == Material.AIR) {
return i;
}
}
return heldSlot;
}
}

Datei anzeigen

@ -18,3 +18,32 @@ java {
tasks.named<Jar>("sourcesJar") {
from(project(":viaversion-api").sourceSets.main.get().allSource)
}
// Task to quickly test/debug code changes using https://github.com/ViaVersion/ViaProxy
// For further instructions see the ViaProxy repository README
tasks.register<JavaExec>("runViaProxy") {
dependsOn(tasks.shadowJar)
val viaProxyConfiguration = configurations.create("viaProxy")
viaProxyConfiguration.dependencies.add(dependencies.create(rootProject.libs.viaProxy.get().copy().setTransitive(false)))
mainClass.set("net.raphimc.viaproxy.ViaProxy")
classpath = viaProxyConfiguration
workingDir = file("run")
jvmArgs = listOf("-DskipUpdateCheck")
if (System.getProperty("viaproxy.gui.autoStart") != null) {
jvmArgs("-Dviaproxy.gui.autoStart")
}
doFirst {
val jarsDir = file("$workingDir/jars")
jarsDir.mkdirs()
file("$jarsDir/${project.name}.jar").writeBytes(tasks.shadowJar.get().archiveFile.get().asFile.readBytes())
}
doLast {
file("$workingDir/jars/${project.name}.jar").delete()
file("$workingDir/logs").deleteRecursively()
}
}

Datei anzeigen

@ -48,7 +48,10 @@ public abstract class ViaListener {
* @return True if on pipe
*/
protected boolean isOnPipe(UUID uuid) {
UserConnection userConnection = getUserConnection(uuid);
return isOnPipe(getUserConnection(uuid));
}
protected boolean isOnPipe(UserConnection userConnection) {
return userConnection != null &&
(requiredPipeline == null || userConnection.getProtocolInfo().getPipeline().contains(requiredPipeline));
}

Datei anzeigen

@ -244,9 +244,12 @@ public class ViaManagerImpl implements ViaManager {
}
if (version < 17) {
platform.getLogger().warning("You are running an outdated Java version, please update it to at least Java 17 (your version is " + javaVersion + ").");
platform.getLogger().warning("You are running an outdated Java version, please update it to at least Java 21 (your version is " + javaVersion + ").");
platform.getLogger().warning("ViaVersion no longer officially supports this version of Java, only offering unsupported compatibility builds.");
platform.getLogger().warning("See https://github.com/ViaVersion/ViaVersion/releases/tag/5.0.0 for more information.");
} else if (version < 21) {
platform.getLogger().warning("Please update your Java runtime to at least Java 21 (your version is " + javaVersion + ").");
platform.getLogger().warning("At some point in the future, ViaVersion will no longer be compatible with this version of Java.");
}
}

Datei anzeigen

@ -30,7 +30,7 @@ public class DumpSubCmd implements ViaSubCommand {
@Override
public String description() {
return "Dump information about your server, this is helpful if you report bugs.";
return "Dump information about your platform implementation, this is helpful if you report bugs.";
}
@Override

Datei anzeigen

@ -35,7 +35,7 @@ public class ReloadSubCmd implements ViaSubCommand {
@Override
public boolean execute(ViaCommandSender sender, String[] args) {
Via.getManager().getConfigurationProvider().reloadConfigs();
sendMessage(sender, "&6Configuration successfully reloaded! Some features may need a restart.");
sendMessage(sender, "&6Configuration successfully reloaded! Some config options may require a restart to take effect.");
return true;
}
}

Datei anzeigen

@ -164,7 +164,7 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
handleInvalidItemCount = getBoolean("handle-invalid-item-count", false);
cancelBlockSounds = getBoolean("cancel-block-sounds", true);
hideScoreboardNumbers = getBoolean("hide-scoreboard-numbers", false);
fix1_21PlacementRotation = getBoolean("fix-1_21-placement-rotation", false);
fix1_21PlacementRotation = getBoolean("fix-1_21-placement-rotation", true);
}
private BlockedProtocolVersions loadBlockedProtocolVersions() {
@ -554,6 +554,6 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
@Override
public boolean fix1_21PlacementRotation() {
return false && fix1_21PlacementRotation; // TODO Can't always set onGround to true
return fix1_21PlacementRotation;
}
}

Datei anzeigen

@ -29,8 +29,8 @@ import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.VarIntType;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
@ -55,6 +55,7 @@ import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public class UserConnectionImpl implements UserConnection {
private static final int PASSTHROUGH_DATA_BYTES = Long.BYTES * 2 + 2;
private static final AtomicLong IDS = new AtomicLong();
private final long id = IDS.incrementAndGet();
private final Map<Class<?>, StorableObject> storedObjects = new ConcurrentHashMap<>();
@ -244,7 +245,8 @@ public class UserConnectionImpl implements UserConnection {
}
private void sendRawPacketToServerServerSide(final ByteBuf packet, final boolean currentThread) {
final ByteBuf buf = packet.alloc().buffer();
final int initialCapacity = active ? packet.readableBytes() + PASSTHROUGH_DATA_BYTES : packet.readableBytes();
final ByteBuf buf = packet.alloc().buffer(initialCapacity);
try {
// We'll use passing through because there are some encoder wrappers
ChannelHandlerContext context = PipelineUtil
@ -333,7 +335,7 @@ public class UserConnectionImpl implements UserConnection {
return;
}
int id = Types.VAR_INT.readPrimitive(buf);
final int id = Types.VAR_INT.readPrimitive(buf);
if (id == PacketWrapper.PASSTHROUGH_ID) {
if (!passthroughTokens.remove(Types.UUID.read(buf))) {
throw new IllegalArgumentException("Invalid token");
@ -341,20 +343,47 @@ public class UserConnectionImpl implements UserConnection {
return;
}
PacketWrapper wrapper = new PacketWrapperImpl(id, buf, this);
State state = protocolInfo.getState(direction);
final int valuesReaderIndex = buf.readerIndex();
final PacketWrapperImpl wrapper = new PacketWrapperImpl(id, buf, this);
try {
protocolInfo.getPipeline().transform(direction, state, wrapper);
} catch (CancelException ex) {
protocolInfo.getPipeline().transform(direction, protocolInfo.getState(direction), wrapper);
} catch (final CancelException ex) {
throw cancelSupplier.apply(ex);
}
ByteBuf transformed = buf.alloc().buffer();
writeToBuffer(wrapper, buf, id, valuesReaderIndex);
}
private void writeToBuffer(final PacketWrapperImpl wrapper, final ByteBuf buf, final int originalId, final int originalReaderIndex) {
final int remainingBytes = buf.readableBytes();
if (buf.readerIndex() == originalReaderIndex && wrapper.areStoredPacketValuesEmpty()) {
if (wrapper.getId() == originalId) {
// No changes needed; just set the reader and writer indexes and we're done
buf.setIndex(0, originalReaderIndex + remainingBytes);
return;
}
if (VarIntType.varIntLength(wrapper.getId()) == VarIntType.varIntLength(originalId)) {
// If the var int encoded length is the same, simply replace the id at the head
buf.setIndex(0, 0);
Types.VAR_INT.writePrimitive(buf, wrapper.getId());
buf.writerIndex(originalReaderIndex + remainingBytes);
return;
}
}
// Instead of allocating a possible unnecessarily large buffer to write the wrapper contents to,
// only allocate the remaining bytes and write the rest to the original buf's head directly.
final ByteBuf remainingBuf = buf.alloc().buffer(remainingBytes, remainingBytes);
try {
wrapper.writeToBuffer(transformed);
buf.clear().writeBytes(transformed);
// Copy before modifying the buffer
remainingBuf.writeBytes(buf, remainingBytes);
// Reset indexes, write wrapper contents, then the unread bytes
buf.setIndex(0, 0);
wrapper.writeProcessedValues(buf);
buf.writeBytes(remainingBuf);
} finally {
transformed.release();
remainingBuf.release();
}
}

Datei anzeigen

@ -76,6 +76,8 @@ import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.Protocol1_20_3To1_20_5;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20to1_20_2.Protocol1_20To1_20_2;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.Protocol1_21To1_21_2;
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.Protocol1_9_1To1_9_3;
import com.viaversion.viaversion.protocols.v1_9_3to1_10.Protocol1_9_3To1_10;
@ -192,6 +194,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
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);
registerProtocol(new Protocol1_21To1_21_2(), ProtocolVersion.v1_21_2, ProtocolVersion.v1_21);
registerProtocol(new Protocol1_21_2To1_21_4(), ProtocolVersion.v1_21_4, ProtocolVersion.v1_21_2);
}
@Override

Datei anzeigen

@ -222,6 +222,18 @@ public class PacketWrapperImpl implements PacketWrapper {
@Override
public void writeToBuffer(ByteBuf buffer) throws InformativeException {
writeProcessedValues(buffer);
if (inputBuffer != null) {
buffer.writeBytes(inputBuffer);
}
}
public boolean areStoredPacketValuesEmpty() {
// Check for read/added packet values, not the input buffer
return packetValues.isEmpty() && readableObjects.isEmpty();
}
public void writeProcessedValues(ByteBuf buffer) throws InformativeException {
if (id != -1) {
Types.VAR_INT.writePrimitive(buffer, id);
}
@ -238,16 +250,15 @@ public class PacketWrapperImpl implements PacketWrapper {
throw createInformativeException(e, packetValue.type(), i);
}
}
writeRemaining(buffer);
}
private InformativeException createInformativeException(final Exception cause, final Type<?> type, final int index) {
return new InformativeException(cause)
.set("Packet Type", this.packetType)
.set("Index", index)
.set("Type", type.getTypeName())
.set("Packet ID", this.id)
.set("Packet Type", this.packetType)
.set("Data", this.packetValues);
.set("Data", this.packetValues)
.set("Packet ID", this.id);
}
@Override
@ -264,12 +275,6 @@ public class PacketWrapperImpl implements PacketWrapper {
packetValues.clear();
}
private void writeRemaining(ByteBuf output) {
if (inputBuffer != null) {
output.writeBytes(inputBuffer);
}
}
@Override
public void send(Class<? extends Protocol> protocol, boolean skipCurrentPipeline) throws InformativeException {
send0(protocol, skipCurrentPipeline, true);
@ -320,7 +325,7 @@ public class PacketWrapperImpl implements PacketWrapper {
final ProtocolInfo protocolInfo = user().getProtocolInfo();
final List<Protocol> protocols = protocolInfo.getPipeline().pipes(protocolClass, skipCurrentPipeline, direction);
apply(direction, protocolInfo.getState(direction), protocols);
final ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
final ByteBuf output = allocateOutputBuffer();
try {
writeToBuffer(output);
return output.retain();
@ -354,7 +359,7 @@ public class PacketWrapperImpl implements PacketWrapper {
return cancelledFuture();
}
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
ByteBuf output = allocateOutputBuffer();
try {
writeToBuffer(output);
return user().sendRawPacketFuture(output.retain());
@ -373,7 +378,7 @@ public class PacketWrapperImpl implements PacketWrapper {
return;
}
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
ByteBuf output = allocateOutputBuffer();
try {
writeToBuffer(output);
if (currentThread) {
@ -386,6 +391,14 @@ public class PacketWrapperImpl implements PacketWrapper {
}
}
private ByteBuf allocateOutputBuffer() {
if (inputBuffer == null) {
return user().getChannel().alloc().buffer();
}
// May have already been partially or fully read
return inputBuffer.alloc().buffer(Math.max(inputBuffer.readableBytes(), 256));
}
private ChannelFuture cancelledFuture() {
return user().getChannel().newFailedFuture(new RuntimeException("Tried to send cancelled packet"));
}
@ -454,7 +467,7 @@ public class PacketWrapperImpl implements PacketWrapper {
return;
}
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
ByteBuf output = allocateOutputBuffer();
try {
writeToBuffer(output);
if (currentThread) {

Datei anzeigen

@ -23,11 +23,14 @@ import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket;
public enum ClientboundLoginPackets implements BaseClientboundPacket {
LOGIN_DISCONNECT, // 0x00
HELLO, // 0x01
GAME_PROFILE, // 0x02
LOGIN_FINISHED, // 0x02
LOGIN_COMPRESSION, // 0x03
CUSTOM_QUERY, // 0x04
COOKIE_REQUEST; // 0x05
@Deprecated(forRemoval = true)
public static final ClientboundLoginPackets GAME_PROFILE = LOGIN_FINISHED;
@Override
public final int getId() {
return ordinal();

Datei anzeigen

@ -128,7 +128,7 @@ public class ClientboundBaseProtocol1_7 extends AbstractProtocol<BaseClientbound
});
// Track player name/uuid and setup connection + track state
registerClientbound(ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
registerClientbound(ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
final ProtocolInfo info = wrapper.user().getProtocolInfo();
if (info.serverProtocolVersion().olderThan(ProtocolVersion.v1_16)) {

Datei anzeigen

@ -18,27 +18,26 @@
package com.viaversion.viaversion.protocols.template;
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.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
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.packet.ClientboundPacket1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
// To replace if needed:
// ChunkType1_20_2
// RecipeRewriter1_20_3
// Types1_21, Types1_OLD
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_99To_98> {
// RecipeDisplayRewriter
// Types1_21_4, Types1_OLD
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21_2, ServerboundPacket1_21_4, Protocol1_99To_98> {
public BlockItemPacketRewriter1_99(final Protocol1_99To_98 protocol) {
super(protocol, Types1_21.ITEM, Types1_21.ITEM_ARRAY);
super(protocol, Types1_21_4.ITEM, Types1_21_4.ITEM_ARRAY);
/*super(protocol,
Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY, Types1_21.ITEM, Types1_21.ITEM_ARRAY,
Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST, Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST,
Types1_OLD.PARTICLE, Types1_21.PARTICLE
Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY, Types1_21_4.ITEM, Types1_21_4.ITEM_ARRAY,
Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST, Types1_21_4.ITEM_COST, Types1_21_4.OPTIONAL_ITEM_COST
);*/
}
@ -47,31 +46,33 @@ final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Clientbou
// Register block and block state id changes
// Other places using block state id mappings: Spawn particle, entity data, entity spawn (falling blocks)
// Tags and statistics use block (!) ids
final BlockRewriter<ClientboundPacket1_21> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21.BLOCK_ENTITY_DATA);
final BlockRewriter<ClientboundPacket1_21_2> blockRewriter = BlockRewriter.for1_20_2(protocol);
blockRewriter.registerBlockEvent(ClientboundPackets1_21_2.BLOCK_EVENT);
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_2.BLOCK_UPDATE);
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_2.SECTION_BLOCKS_UPDATE);
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_2.LEVEL_EVENT, 2001);
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_2.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_2.BLOCK_ENTITY_DATA);
// Registers item id changes
// Other places using item ids are: Entity data, tags, statistics, effect
// registerOpenWindow(ClientboundPackets1_21.OPEN_WINDOW); - If a new container type was added
registerCooldown(ClientboundPackets1_21.COOLDOWN);
registerSetContent1_17_1(ClientboundPackets1_21.CONTAINER_SET_CONTENT);
registerSetSlot1_17_1(ClientboundPackets1_21.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21.SET_EQUIPMENT);
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS);
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
registerExplosion(ClientboundPackets1_21.EXPLODE); // Rewrites the included sound and particles
// registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
registerSetPlayerInventory(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY);
registerCooldown1_21_2(ClientboundPackets1_21_2.COOLDOWN);
registerSetContent1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT);
registerSetSlot1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_SLOT);
registerAdvancements1_20_3(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS);
registerSetEquipment(ClientboundPackets1_21_2.SET_EQUIPMENT);
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
registerContainerClick1_21_2(ServerboundPackets1_21_4.CONTAINER_CLICK);
registerSetCreativeModeSlot(ServerboundPackets1_21_4.SET_CREATIVE_MODE_SLOT);
new RecipeRewriter1_20_3<>(protocol).register1_20_5(ClientboundPackets1_21.UPDATE_RECIPES);
final RecipeDisplayRewriter<ClientboundPacket1_21_2> recipeRewriter = new RecipeDisplayRewriter<>(protocol);
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_2.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_2.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE);
// OR do this if serialization of recipes changed and override the relevant method
// Add new serializers to RecipeRewriter, or extend the last one for changes
// new RecipeRewriter1_20_3<ClientboundPacket1_21>(this) {}.register1_20_5(ClientboundPackets1_21.DECLARE_RECIPES);
// Add new serializers to RecipeDisplayRewriter, or extend the last one for changes
}
}

Datei anzeigen

@ -0,0 +1,46 @@
/*
* 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.template;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.util.SerializerVersion;
final class ComponentRewriter1_99 extends ComponentRewriter<ClientboundPacket1_21_2> {
public ComponentRewriter1_99(final Protocol1_99To_98 protocol) {
super(protocol, ReadType.NBT);
}
@Override
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
super.handleShowItem(connection, itemTag, componentsTag);
if (componentsTag == null) {
return;
}
// Remove or update data from componentsTag
}
@Override
protected SerializerVersion inputSerializerVersion() {
return SerializerVersion.V1_21_4;
}
}

Datei anzeigen

@ -17,22 +17,20 @@
*/
package com.viaversion.viaversion.protocols.template;
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;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
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_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
// Replace if needed
// Types1_OLD
// Types1_21
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21, Protocol1_99To_98> {
// Types1_21_4
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21_2, Protocol1_99To_98> {
public EntityPacketRewriter1_99(final Protocol1_99To_98 protocol) {
super(protocol);
@ -41,36 +39,32 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
@Override
public void registerPackets() {
// Tracks entities, applies entity data rewrites registered below, untracks entities
registerTrackerWithData1_19(ClientboundPackets1_21.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_21.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_21.REMOVE_ENTITIES);
registerTrackerWithData1_19(ClientboundPackets1_21_2.ADD_ENTITY, EntityTypes1_21_4.FALLING_BLOCK);
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_21_4.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
protocol.registerClientbound(ClientboundConfigurationPackets1_21.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
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
final int entityId = wrapper.passthrough(Types.INT); // Entity id
wrapper.passthrough(Types.BOOLEAN); // Hardcore
wrapper.passthrough(Types.STRING_ARRAY); // World List
wrapper.passthrough(Types.VAR_INT); // Max players
wrapper.passthrough(Types.VAR_INT); // View distance
wrapper.passthrough(Types.VAR_INT); // Simulation distance
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
wrapper.passthrough(Types.BOOLEAN); // Show death screen
wrapper.passthrough(Types.BOOLEAN); // Limited crafting
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
final String world = wrapper.passthrough(Types.STRING);
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
trackPlayer(wrapper.user(), entityId);
});
protocol.registerClientbound(ClientboundPackets1_21.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)); // Tracks world height and name for chunk data and entity (un)tracking
handler(playerTrackerHandler());
}
});
protocol.registerClientbound(ClientboundPackets1_21.RESPAWN, wrapper -> {
protocol.registerClientbound(ClientboundPackets1_21_2.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
@ -85,20 +79,20 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
if (id >= SomeAddedIndex) {
id++;
}
return Types1_21.ENTITY_DATA_TYPES.byId(id);
return Types1_21_4.ENTITY_DATA_TYPES.byId(id);
});*/
// Registers registry type id changes
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
Types1_21_4.ENTITY_DATA_TYPES.itemType,
Types1_21_4.ENTITY_DATA_TYPES.blockStateType,
Types1_21_4.ENTITY_DATA_TYPES.optionalBlockStateType,
Types1_21_4.ENTITY_DATA_TYPES.particleType,
Types1_21_4.ENTITY_DATA_TYPES.particlesType,
Types1_21_4.ENTITY_DATA_TYPES.componentType,
Types1_21_4.ENTITY_DATA_TYPES.optionalComponentType
);
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
registerBlockStateHandler(EntityTypes1_21_4.ABSTRACT_MINECART, 11);
}
@Override
@ -109,6 +103,6 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
@Override
public EntityType typeFromId(final int type) {
return EntityTypes1_20_5.getTypeFromId(type);
return EntityTypes1_21_4.getTypeFromId(type);
}
}

Datei anzeigen

@ -20,18 +20,21 @@ package com.viaversion.viaversion.protocols.template;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
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.version.Types1_21_4;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
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.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_21_2to1_21_4.packet.ServerboundPacket1_21_4;
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.ComponentRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
@ -40,35 +43,56 @@ import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
// Placeholders to replace (in the entire package):
// Protocol1_99To_98, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99 - move the latter two to a rewriter package
// ClientboundPacket1_21
// ServerboundPacket1_20_5
// EntityTypes1_20_5 (MAPPED type)
// ClientboundPacket1_21_2
// ServerboundPacket1_21_4
// EntityTypes1_21_4 (MAPPED type)
// Types1_21_4.PARTICLE
// 1.99, 1.98
final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_4, ServerboundPacket1_21_4> {
public static final MappingData MAPPINGS = new MappingDataBase("1.98", "1.99");
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
private final TagRewriter<ClientboundPacket1_21> tagRewriter = new TagRewriter<>(this);
private final ParticleRewriter<ClientboundPacket1_21_2> particleRewriter = new ParticleRewriter<>(this, /*Types1_OLD.PARTICLE,*/ Types1_21_4.PARTICLE);
private final TagRewriter<ClientboundPacket1_21_2> tagRewriter = new TagRewriter<>(this);
private final ComponentRewriter<ClientboundPacket1_21_2> componentRewriter = new ComponentRewriter1_99(this);
public Protocol1_99To_98() {
// Passing the class types into the super constructor is needed for automatic packet type id remapping, but can otherwise be omitted
super(ClientboundPacket1_21.class, ClientboundPacket1_21.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
super(ClientboundPacket1_21_2.class, ClientboundPacket1_21_2.class, ServerboundPacket1_21_4.class, ServerboundPacket1_21_4.class);
}
@Override
protected void registerPackets() {
super.registerPackets();
tagRewriter.registerGeneric(ClientboundPackets1_21.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundPackets1_21_2.UPDATE_TAGS);
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
final SoundRewriter<ClientboundPacket1_21> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND_ENTITY);
// If needed for item or component changes
componentRewriter.registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_ACTION_BAR_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_TITLE_TEXT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
componentRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
componentRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISGUISED_CHAT);
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE);
componentRewriter.registerPing();
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21.UPDATE_ATTRIBUTES);
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
particleRewriter.registerLevelParticles1_20_5(ClientboundPackets1_21_2.LEVEL_PARTICLES);
particleRewriter.registerExplode1_21_2(ClientboundPackets1_21_2.EXPLODE); // Rewrites the included sound and particles
final SoundRewriter<ClientboundPacket1_21_2> soundRewriter = new SoundRewriter<>(this);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND_ENTITY);
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_2.AWARD_STATS);
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
/*new CommandRewriter1_19_4<>(this) {
@ -81,25 +105,29 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
super.handleArgument(wrapper, argumentType);
}
}
}.registerDeclareCommands1_19(ClientboundPackets1_21.COMMANDS);*/
}.registerDeclareCommands1_19(ClientboundPackets1_21_2.COMMANDS);*/
}
@Override
protected void onMappingDataLoaded() {
// Uncomment this if the entity types enum has been newly added specifically for this Protocol
// EntityTypes1_20_5.initialize(this);
// EntityTypes1_21_4.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("item", ParticleType.Readers.ITEM1_20_2)
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK);*/
/*Types1_21_4.PARTICLE.filler(this)
.reader("block", ParticleType.Readers.BLOCK)
.reader("block_marker", ParticleType.Readers.BLOCK)
.reader("dust_pillar", ParticleType.Readers.BLOCK)
.reader("falling_dust", ParticleType.Readers.BLOCK)
.reader("block_crumble", ParticleType.Readers.BLOCK)
.reader("dust", ParticleType.Readers.DUST1_21_2)
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION1_21_2)
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
.reader("shriek", ParticleType.Readers.SHRIEK)
.reader("entity_effect", ParticleType.Readers.COLOR)
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));*/
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
}
@ -107,7 +135,7 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
@Override
public void init(final UserConnection connection) {
// Register the entity tracker - used for entity id/entity data rewriting AND for tracking world data sent to the client (then used for chunk data rewriting)
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_4.PLAYER));
}
// Overriding these four methods is important as they are relied on various rewriter classes
@ -128,17 +156,27 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
}
@Override
public TagRewriter<ClientboundPacket1_21> getTagRewriter() {
public ParticleRewriter<ClientboundPacket1_21_2> getParticleRewriter() {
return particleRewriter;
}
@Override
public TagRewriter<ClientboundPacket1_21_2> getTagRewriter() {
return tagRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
public ComponentRewriter<ClientboundPacket1_21_2> getComponentRewriter() {
return componentRewriter;
}
@Override
protected PacketTypesProvider<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_4, ServerboundPacket1_21_4> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.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)
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_4.class, ServerboundConfigurationPackets1_20_5.class),
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_4.class, ServerboundConfigurationPackets1_20_5.class)
);
}
}

Datei anzeigen

@ -132,13 +132,13 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
if (effectID == 2002) {
int data = packetWrapper.get(Types.INT, 1);
boolean isInstant = false;
Pair<Integer, Boolean> newData = PotionColorMappings1_11.getNewData(data);
PotionColorMappings1_11.PotionData newData = PotionColorMappings1_11.getNewData(data);
if (newData == null) {
getLogger().warning("Received unknown potion data: " + data);
data = 0;
} else {
data = newData.key();
isInstant = newData.value();
data = newData.data();
isInstant = newData.instant();
}
if (isInstant) {
packetWrapper.set(Types.INT, 0, 2007);

Datei anzeigen

@ -17,14 +17,13 @@
*/
package com.viaversion.viaversion.protocols.v1_10to1_11.data;
import com.viaversion.viaversion.util.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.checkerframework.checker.nullness.qual.Nullable;
public class PotionColorMappings1_11 {
//<oldData> to <newData, isInstant> mapping
private static final Int2ObjectMap<Pair<Integer, Boolean>> POTIONS = new Int2ObjectOpenHashMap<>(37);
private static final Int2ObjectMap<PotionData> POTIONS = new Int2ObjectOpenHashMap<>(37);
static {
addRewrite(0, 3694022, false);
@ -66,12 +65,14 @@ public class PotionColorMappings1_11 {
addRewrite(36, 3381504, false);
}
public static Pair<Integer, Boolean> getNewData(int oldData) {
public static @Nullable PotionData getNewData(int oldData) {
return POTIONS.get(oldData);
}
private static void addRewrite(int oldData, int newData, boolean isInstant) {
POTIONS.put(oldData, new Pair<>(newData, isInstant));
POTIONS.put(oldData, new PotionData(newData, isInstant));
}
public record PotionData(int data, boolean instant) {
}
}

Datei anzeigen

@ -24,9 +24,9 @@ import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11.EntityType;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_9;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.type.Types;
@ -37,6 +37,7 @@ import com.viaversion.viaversion.protocols.v1_10to1_11.data.EntityMappings1_11;
import com.viaversion.viaversion.protocols.v1_10to1_11.storage.EntityTracker1_11;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
@ -91,13 +92,27 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
map(Types.INT); // 8 - Data
// Track Entity
handler(objectTrackerHandler());
handler(wrapper -> {
byte type = wrapper.get(Types.BYTE, 0);
if (type == EntityTypes1_10.ObjectType.FISHIHNG_HOOK.getId()) {
tryFixFishingHookVelocity(wrapper);
} else if (type == EntityTypes1_10.ObjectType.ITEM.getId()) {
// Older clients used stone as fallback as long as the entity data was not set
wrapper.send(Protocol1_10To1_11.class);
wrapper.cancel();
final int entityId = wrapper.get(Types.VAR_INT, 0);
final List<EntityData> entityDataList = new ArrayList<>();
entityDataList.add(new EntityData(6, EntityDataTypes1_9.ITEM, new DataItem(1, (byte) 1, null)));
final PacketWrapper setItem = PacketWrapper.create(ClientboundPackets1_9_3.SET_ENTITY_DATA, wrapper.user());
setItem.write(Types.VAR_INT, entityId);
setItem.write(Types1_9.ENTITY_DATA_LIST, entityDataList);
setItem.send(Protocol1_10To1_11.class);
}
});
handler(objectTrackerHandler());
}
});

Datei anzeigen

@ -34,6 +34,7 @@ import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.Types1_13;
@ -145,7 +146,7 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
}).scheduleSend(Protocol1_12_2To1_13.class);
// Send tags packet
w.create(ClientboundPackets1_13.UPDATE_TAGS, wrapper -> {
final PacketWrapper tagsPacket = w.create(ClientboundPackets1_13.UPDATE_TAGS, wrapper -> {
wrapper.write(Types.VAR_INT, MAPPINGS.getBlockTags().size()); // block tags
for (Map.Entry<String, int[]> tag : MAPPINGS.getBlockTags().entrySet()) {
wrapper.write(Types.STRING, tag.getKey());
@ -164,7 +165,13 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
// Needs copy as other protocols may modify it
wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, tag.getValue().clone());
}
}).scheduleSend(Protocol1_12_2To1_13.class);
});
if (w.user().getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_5)) {
// Make sure it's included in the configuration packets as it may already be required for registry data
tagsPacket.send(Protocol1_12_2To1_13.class);
} else {
tagsPacket.scheduleSend(Protocol1_12_2To1_13.class);
}
};
@Override
@ -346,7 +353,7 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
registerClientbound(ClientboundPackets1_12_1.PLACE_GHOST_RECIPE, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE);
map(Types.UNSIGNED_BYTE);
handler(wrapper -> wrapper.write(Types.STRING, "viaversion:legacy/" + wrapper.read(Types.VAR_INT)));
}
});
@ -587,7 +594,7 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
registerServerbound(ServerboundPackets1_13.PLACE_RECIPE, new PacketHandlers() {
@Override
public void register() {
map(Types.BYTE); // Window id
map(Types.UNSIGNED_BYTE); // Window id
handler(wrapper -> {
String s = wrapper.read(Types.STRING);
@ -768,7 +775,10 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
for (Item[] ingredient : recipe.ingredients()) {
Item[] clone = new Item[ingredient.length];
for (int i = 0; i < ingredient.length; i++) {
if (clone[i] == null) continue;
if (ingredient[i] == null) {
continue;
}
clone[i] = ingredient[i].copy();
}
recipesPacket.write(Types.ITEM1_13_ARRAY, clone);
@ -782,7 +792,10 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
for (Item[] ingredient : recipe.ingredients()) {
Item[] clone = new Item[ingredient.length];
for (int i = 0; i < ingredient.length; i++) {
if (clone[i] == null) continue;
if (ingredient[i] == null) {
continue;
}
clone[i] = ingredient[i].copy();
}
recipesPacket.write(Types.ITEM1_13_ARRAY, clone);
@ -793,7 +806,10 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
recipesPacket.write(Types.STRING, recipe.group());
Item[] ingredient = new Item[recipe.ingredient().length];
for (int i = 0; i < ingredient.length; i++) {
if (recipe.ingredient()[i] == null) continue;
if (recipe.ingredient()[i] == null) {
continue;
}
ingredient[i] = recipe.ingredient()[i].copy();
}
recipesPacket.write(Types.ITEM1_13_ARRAY, ingredient);

Datei anzeigen

@ -33,6 +33,7 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.blockentities.
import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.blockentities.FlowerPotHandler;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.blockentities.SkullHandler;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.blockentities.SpawnerHandler;
import com.viaversion.viaversion.util.ComponentUtil;
import java.util.HashMap;
import java.util.Map;
@ -46,6 +47,21 @@ public class BlockEntityProvider implements Provider {
handlers.put("minecraft:skull", new SkullHandler());
handlers.put("minecraft:mob_spawner", new SpawnerHandler());
handlers.put("minecraft:command_block", new CommandBlockHandler());
final BlockEntityHandler customNameHandler = (user, tag) -> {
final StringTag name = tag.getStringTag("CustomName");
if (name != null) {
name.setValue(ComponentUtil.legacyToJsonString(name.getValue()));
}
return -1;
};
handlers.put("minecraft:chest", customNameHandler);
handlers.put("minecraft:dispenser", customNameHandler);
handlers.put("minecraft:dropper", customNameHandler);
handlers.put("minecraft:enchanting_table", customNameHandler);
handlers.put("minecraft:furnace", customNameHandler);
handlers.put("minecraft:hopper", customNameHandler);
handlers.put("minecraft:shulker_box", customNameHandler);
}
/**

Datei anzeigen

@ -18,16 +18,19 @@
package com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.blockentities;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.BlockEntityProvider;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Pair;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class FlowerPotHandler implements BlockEntityProvider.BlockEntityHandler {
// Object -> string (id without namespace) or byte (numeric id)
private static final Map<Pair<?, Byte>, Integer> flowers = new ConcurrentHashMap<>();
private static final int EMPTY_POT = 5265;
private static final Map<String, Byte> STRING_TO_BYTE_ID = new HashMap<>();
private static final Map<IntIdPair, Integer> FLOWERS = new HashMap<>();
static {
register("air", (byte) 0, (byte) 0, 5265);
@ -55,37 +58,40 @@ public class FlowerPotHandler implements BlockEntityProvider.BlockEntityHandler
}
public static void register(String identifier, byte numbericBlockId, byte blockData, int newId) {
flowers.put(new Pair<>(identifier, blockData), newId);
flowers.put(new Pair<>(numbericBlockId, blockData), newId);
private static void register(String identifier, byte blockId, byte blockData, int newId) {
STRING_TO_BYTE_ID.put(identifier, blockId);
FLOWERS.put(new IntIdPair(blockId, blockData), newId);
}
@Override
public int transform(UserConnection user, CompoundTag tag) {
Object item = tag.contains("Item") ? tag.get("Item").getValue() : null;
Object data = tag.contains("Data") ? tag.get("Data").getValue() : null;
// Convert item to String without namespace or to Byte
if (item instanceof String) {
item = Key.stripMinecraftNamespace((String) item);
} else if (item instanceof Number) {
item = ((Number) item).byteValue();
} else {
item = (byte) 0;
Tag itemTag = tag.get("Item");
byte item = 0;
if (itemTag instanceof StringTag stringTag) {
item = STRING_TO_BYTE_ID.getOrDefault(Key.stripMinecraftNamespace(stringTag.getValue()), (byte) 0);
} else if (itemTag instanceof NumberTag numberTag) {
item = numberTag.asByte();
}
// Convert data to Byte
if (data instanceof Number) {
data = ((Number) data).byteValue();
} else {
data = (byte) 0;
byte data = 0;
if (tag.get("Data") instanceof NumberTag dataTag) {
data = dataTag.asByte();
}
Integer flower = flowers.get(new Pair<>(item, (byte) data));
if (flower != null) return flower;
flower = flowers.get(new Pair<>(item, (byte) 0));
if (flower != null) return flower;
Integer flower = FLOWERS.get(new IntIdPair(item, data));
if (flower != null) {
return flower;
}
return 5265; // Fallback to empty pot
flower = FLOWERS.get(new IntIdPair(item, (byte) 0));
if (flower != null) {
return flower;
}
return EMPTY_POT; // Fallback to empty pot
}
private record IntIdPair(int id, byte data) {
}
}

Datei anzeigen

@ -205,23 +205,23 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
String old = channel;
channel = getOldPluginChannelId(channel);
if (channel == null) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
if (Via.getManager().isDebug()) {
protocol.getLogger().warning("Ignoring serverbound plugin message with channel: " + old);
}
wrapper.cancel();
return;
} else if (channel.equals("REGISTER") || channel.equals("UNREGISTER")) {
String[] channels = new String(wrapper.read(Types.REMAINING_BYTES), StandardCharsets.UTF_8).split("\0");
String[] channels = new String(wrapper.read(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA), StandardCharsets.UTF_8).split("\0");
List<String> rewrittenChannels = new ArrayList<>();
for (String s : channels) {
String rewritten = getOldPluginChannelId(s);
if (rewritten != null) {
rewrittenChannels.add(rewritten);
} else if (!Via.getConfig().isSuppressConversionWarnings()) {
} else if (Via.getManager().isDebug()) {
protocol.getLogger().warning("Ignoring plugin channel in serverbound " + channel + ": " + s);
}
}
wrapper.write(Types.REMAINING_BYTES, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
wrapper.write(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
}
wrapper.set(Types.STRING, 0, channel);
});

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen