Compare commits
69
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd1fad2dd7 | ||
|
|
245f7e24e4 | ||
|
|
9d3db4cf97 | ||
|
|
b67ebecce8 | ||
|
|
d03207289e | ||
|
|
64497b305a | ||
|
|
f5b3799db9 | ||
|
|
00fedc7656 | ||
|
|
05aa05c5b4 | ||
|
|
5243c1800e | ||
|
|
77d702bc9b | ||
|
|
c098e24c4f | ||
|
|
3d083cf463 | ||
|
|
2ab62a8f4f | ||
|
|
296f42086f | ||
|
|
e9f547f7ba | ||
|
|
b7f388b9ee | ||
|
|
824ff375d4 | ||
|
|
8bec05ed38 | ||
|
|
b367caa4b2 | ||
|
|
1c281abf65 | ||
|
|
0a55311e1c | ||
|
|
d1d279cfea | ||
|
|
4b44ecf6fa | ||
|
|
b9474335e8 | ||
|
|
f0c26d5967 | ||
|
|
aa312f7332 | ||
|
|
4210463505 | ||
|
|
ec976dfb6c | ||
|
|
7e60300e2e | ||
|
|
9a9ca9676d | ||
|
|
c68915b261 | ||
|
|
524e053327 | ||
|
|
9e523c353a | ||
|
|
00088a90fd | ||
|
|
ddf6df8097 | ||
|
|
794683ef75 | ||
|
|
cc6f789334 | ||
|
|
4a70e0ea2a | ||
|
|
72cc9e9968 | ||
|
|
1039b8556b | ||
|
|
e977e8db90 | ||
|
|
877053c471 | ||
|
|
67a349d74b | ||
|
|
009e2deed1 | ||
|
|
bb59149fbd | ||
|
|
089df6517e | ||
|
|
d007beaeec | ||
|
|
3d656d411d | ||
|
|
2c44c275bc | ||
|
|
d062229e0f | ||
|
|
8bc22a1bad | ||
|
|
5d0846abe2 | ||
|
|
23dd8c55ad | ||
|
|
5edb6ff411 | ||
|
|
251ab42c14 | ||
|
|
134c3559bf | ||
|
|
832dbdf493 | ||
|
|
ccc509432b | ||
|
|
cf2168aa95 | ||
|
|
58d7dc7ca6 | ||
|
|
1fe6f72aec | ||
|
|
e3312b1c80 | ||
|
|
182148dbe8 | ||
|
|
b5c718098d | ||
|
|
01ea51e8ee | ||
|
|
ae3042074e | ||
|
|
d0ed528788 | ||
|
|
2fba2c1e65 |
No files matched your search
@@ -11,6 +11,9 @@ The base ViaVersion jar runs on Paper and Velocity. We also have projects integr
|
||||
on Fabric, Forge, Bungee, Sponge, or as a standalone proxy to join from basically any client version on
|
||||
any server version from the past decade. **See [HERE](https://github.com/ViaVersion) for an overview of the different Via\* projects.**
|
||||
|
||||
Note that ViaVersion will be able to **run best on either Paper servers or Fabric clients** due to having
|
||||
direct access to client/server state and more extensive API.
|
||||
|
||||
Supported Versions:
|
||||
|
||||

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