mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2026-11-04 17:00:06 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
488a6b6919 | ||
|
|
3cd01978df | ||
|
|
0c4dbbe0bb | ||
|
|
1750131831 | ||
|
|
5ac7aaccb7 | ||
|
|
ae60e2f28d | ||
|
|
17a73dff82 | ||
|
|
5e9d213082 | ||
|
|
210b0a6f0e | ||
|
|
f0f87b26d7 | ||
|
|
45a55a81c7 | ||
|
|
b2ec9eab50 | ||
|
|
2f08f0d58c | ||
|
|
d3f92ce9b8 | ||
|
|
cfa20ba418 | ||
|
|
de6ac47a2f | ||
|
|
b41733bdf6 | ||
|
|
8f8bc55bd0 | ||
|
|
81d92a728d | ||
|
|
68666d2d44 | ||
|
|
e539375143 | ||
|
|
0acec719b1 | ||
|
|
93e92ffc82 | ||
|
|
82c55b1d78 | ||
|
|
dd660a2de0 | ||
|
|
96c12ef483 | ||
|
|
1653de70c8 | ||
|
|
b57265e64f | ||
|
|
9d4af84872 | ||
|
|
40665782e7 | ||
|
|
2d663db53f | ||
|
|
896c6accfb | ||
|
|
1785677901 | ||
|
|
e32205ddaf | ||
|
|
f93c64d6aa | ||
|
|
b5eb568515 | ||
|
|
7897fca5be | ||
|
|
3ba86741f9 | ||
|
|
5515011644 | ||
|
|
f59e2a2de4 | ||
|
|
88c103c0a5 | ||
|
|
5772ee4a93 | ||
|
|
c525575d37 | ||
|
|
b8a170873d | ||
|
|
04e936d487 | ||
|
|
6553fc9ae9 | ||
|
|
ddbe8ef0fb | ||
|
|
8e4da81022 | ||
|
|
1620fc35f5 | ||
|
|
e878d77959 | ||
|
|
deab6a0cac | ||
|
|
77f0826ec8 | ||
|
|
76db43cab3 | ||
|
|
f0eab71644 | ||
|
|
e9985adafc | ||
|
|
157a1fe249 | ||
|
|
d48d0a21db | ||
|
|
908078becb |
No files matched your search
@@ -1,2 +1,3 @@
|
||||
github: kennytv
|
||||
patreon: kennytv
|
||||
custom: ['https://florianmichael.de/donate']
|
||||
@@ -20,6 +20,13 @@ Supported Versions:
|
||||
|
||||
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
|
||||
|
||||
Snapshot support
|
||||
--------
|
||||
**ViaVersion will only be released a few days *after* a Minecraft update** unless the protocol changes of the update were trivial. If you want early-access, usually days or even weeks before the final release, you can subscribe to either:
|
||||
- [GitHub Sponsors](https://github.com/sponsors/kennytv/sponsorships?sponsor=kennytv&tier_id=385613&preview=false) (preferred option. Use the `/verify` command on this Discord after), or alternatively
|
||||
- [Patreon](https://www.patreon.com/kennytv/membership) (see the highest tier and make sure to link Patreon to your Discord account under Settings->Connections)
|
||||
This also includes access to a private repository with the code, which will be pushed to the public repository after the given delay on a Minecraft update.
|
||||
|
||||
Releases/Dev Builds
|
||||
--------
|
||||
You can find official releases in the following places:
|
||||
|
||||
@@ -478,4 +478,12 @@ public interface ViaVersionConfig extends Config {
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean fix1_21PlacementRotation();
|
||||
|
||||
/**
|
||||
* If enabled, 1.20.5+ clients will have sword blocking mechanics on 1.8 servers using the consumable item component.
|
||||
* Note that you won't be able to see the blocking in first person if the client is older than 1.21.4.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean swordBlockingViaConsumable();
|
||||
}
|
||||
@@ -95,7 +95,7 @@ public class FullMappingsBase implements FullMappings {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mappedIdentifier(final int mappedId) {
|
||||
public @Nullable String mappedIdentifier(final int mappedId) {
|
||||
if (mappedId < 0 || mappedId >= mappedIdToString.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,13 @@ public class BlockPosition {
|
||||
return new BlockPosition(x + face.modX(), y + face.modY(), z + face.modZ());
|
||||
}
|
||||
|
||||
public double distanceFromCenterSquared(final double x, final double y, final double z) {
|
||||
final double dx = this.x + 0.5 - x;
|
||||
final double dy = this.y + 0.5 - y;
|
||||
final double dz = this.z + 0.5 - z;
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
}
|
||||
|
||||
public int x() {
|
||||
return x;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,17 @@ public final class ChunkPosition {
|
||||
return (long) chunkX & 0xffffffffL | ((long) chunkZ & 0xffffffffL) << 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a long key for the given block coordinates.
|
||||
*
|
||||
* @param x the block X coordinate
|
||||
* @param z the block Z coordinate
|
||||
* @return the chunk key
|
||||
*/
|
||||
public static long chunkKeyForBlock(final int x, final int z) {
|
||||
return chunkKey(x >> 4, z >> 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
|
||||
+15
-5
@@ -36,6 +36,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
|
||||
@@ -59,9 +60,11 @@ import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.util.Unit;
|
||||
|
||||
public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
@@ -74,14 +77,15 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<Tag> CUSTOM_NAME = new StructuredDataKey<>("custom_name", Types.TAG);
|
||||
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TAG);
|
||||
public static final StructuredDataKey<String> ITEM_MODEL = new StructuredDataKey<>("item_model", Types.STRING);
|
||||
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", Types.TAG_ARRAY);
|
||||
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", new ArrayType<>(Types.TAG, 256));
|
||||
public static final StructuredDataKey<Integer> RARITY = new StructuredDataKey<>("rarity", Types.VAR_INT);
|
||||
public static final StructuredDataKey<Enchantments> ENCHANTMENTS = new StructuredDataKey<>("enchantments", Enchantments.TYPE);
|
||||
public static final StructuredDataKey<AdventureModePredicate> CAN_PLACE_ON = new StructuredDataKey<>("can_place_on", AdventureModePredicate.TYPE);
|
||||
public static final StructuredDataKey<AdventureModePredicate> CAN_BREAK = new StructuredDataKey<>("can_break", AdventureModePredicate.TYPE);
|
||||
public static final StructuredDataKey<AttributeModifiers1_20_5> ATTRIBUTE_MODIFIERS1_20_5 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_20_5.TYPE);
|
||||
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE);
|
||||
public static final StructuredDataKey<Integer> CUSTOM_MODEL_DATA = new StructuredDataKey<>("custom_model_data", Types.VAR_INT);
|
||||
public static final StructuredDataKey<Integer> CUSTOM_MODEL_DATA1_20_5 = new StructuredDataKey<>("custom_model_data", Types.VAR_INT);
|
||||
public static final StructuredDataKey<CustomModelData1_21_4> CUSTOM_MODEL_DATA1_21_4 = new StructuredDataKey<>("custom_model_data", CustomModelData1_21_4.TYPE);
|
||||
public static final StructuredDataKey<Unit> HIDE_ADDITIONAL_TOOLTIP = new StructuredDataKey<>("hide_additional_tooltip", Types.EMPTY);
|
||||
public static final StructuredDataKey<Unit> HIDE_TOOLTIP = new StructuredDataKey<>("hide_tooltip", Types.EMPTY);
|
||||
public static final StructuredDataKey<Integer> REPAIR_COST = new StructuredDataKey<>("repair_cost", Types.VAR_INT);
|
||||
@@ -92,7 +96,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_21);
|
||||
public static final StructuredDataKey<FoodProperties1_21_2> FOOD1_21_2 = new StructuredDataKey<>("food", FoodProperties1_21_2.TYPE);
|
||||
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
|
||||
public static final StructuredDataKey<Item> USE_REMAINDER = new StructuredDataKey<>("use_remainder", Types1_21_2.ITEM);
|
||||
public static final StructuredDataKey<Item> USE_REMAINDER1_21_2 = new StructuredDataKey<>("use_remainder", Types1_21_2.ITEM);
|
||||
public static final StructuredDataKey<Item> USE_REMAINDER1_21_4 = new StructuredDataKey<>("use_remainder", Types1_21_4.ITEM);
|
||||
public static final StructuredDataKey<UseCooldown> USE_COOLDOWN = new StructuredDataKey<>("use_cooldown", UseCooldown.TYPE);
|
||||
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
|
||||
public static final StructuredDataKey<DamageResistant> DAMAGE_RESISTANT = new StructuredDataKey<>("damage_resistant", DamageResistant.TYPE);
|
||||
@@ -112,15 +117,19 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_20_5 = new StructuredDataKey<>("charged_projectiles", Types1_20_5.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21 = new StructuredDataKey<>("charged_projectiles", Types1_21.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_2 = new StructuredDataKey<>("charged_projectiles", Types1_21_2.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_4 = new StructuredDataKey<>("charged_projectiles", Types1_21_4.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_20_5 = new StructuredDataKey<>("bundle_contents", Types1_20_5.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21 = new StructuredDataKey<>("bundle_contents", Types1_21.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_2 = new StructuredDataKey<>("bundle_contents", Types1_21_2.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_4 = new StructuredDataKey<>("bundle_contents", Types1_21_4.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_20_5 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_20_5);
|
||||
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_21_2 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_21_2);
|
||||
public static final StructuredDataKey<SuspiciousStewEffect[]> SUSPICIOUS_STEW_EFFECTS = new StructuredDataKey<>("suspicious_stew_effects", SuspiciousStewEffect.ARRAY_TYPE);
|
||||
public static final StructuredDataKey<FilterableString[]> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", FilterableString.ARRAY_TYPE);
|
||||
public static final StructuredDataKey<WrittenBook> WRITTEN_BOOK_CONTENT = new StructuredDataKey<>("written_book_content", WrittenBook.TYPE);
|
||||
public static final StructuredDataKey<ArmorTrim> TRIM = new StructuredDataKey<>("trim", ArmorTrim.TYPE);
|
||||
public static final StructuredDataKey<ArmorTrim> TRIM1_20_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_20_5);
|
||||
public static final StructuredDataKey<ArmorTrim> TRIM1_21_2 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_2);
|
||||
public static final StructuredDataKey<ArmorTrim> TRIM1_21_4 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_4);
|
||||
public static final StructuredDataKey<CompoundTag> DEBUG_STICK_STATE = new StructuredDataKey<>("debug_stick_state", Types.COMPOUND_TAG);
|
||||
public static final StructuredDataKey<CompoundTag> ENTITY_DATA = new StructuredDataKey<>("entity_data", Types.COMPOUND_TAG);
|
||||
public static final StructuredDataKey<CompoundTag> BUCKET_ENTITY_DATA = new StructuredDataKey<>("bucket_entity_data", Types.COMPOUND_TAG);
|
||||
@@ -140,7 +149,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_20_5 = new StructuredDataKey<>("container", Types1_20_5.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_21 = new StructuredDataKey<>("container", Types1_21.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_21_2 = new StructuredDataKey<>("container", Types1_21_2.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_21_2 = new StructuredDataKey<>("container", new ArrayType<>(Types1_21_2.ITEM, 256));
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_21_4 = new StructuredDataKey<>("container", Types1_21_4.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<BlockStateProperties> BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE);
|
||||
public static final StructuredDataKey<Bee[]> BEES = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE);
|
||||
public static final StructuredDataKey<Tag> LOCK = new StructuredDataKey<>("lock", Types.TAG);
|
||||
|
||||
+313
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.entities;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.util.EntityTypeUtil;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import java.util.Locale;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public enum EntityTypes1_21_4 implements EntityType {
|
||||
|
||||
ENTITY(null, null),
|
||||
|
||||
AREA_EFFECT_CLOUD(ENTITY),
|
||||
END_CRYSTAL(ENTITY),
|
||||
EVOKER_FANGS(ENTITY),
|
||||
EXPERIENCE_ORB(ENTITY),
|
||||
EYE_OF_ENDER(ENTITY),
|
||||
FALLING_BLOCK(ENTITY),
|
||||
ITEM(ENTITY),
|
||||
TNT(ENTITY),
|
||||
OMINOUS_ITEM_SPAWNER(ENTITY),
|
||||
MARKER(ENTITY),
|
||||
LIGHTNING_BOLT(ENTITY),
|
||||
INTERACTION(ENTITY),
|
||||
|
||||
DISPLAY(ENTITY, null),
|
||||
BLOCK_DISPLAY(DISPLAY),
|
||||
ITEM_DISPLAY(DISPLAY),
|
||||
TEXT_DISPLAY(DISPLAY),
|
||||
|
||||
// Hanging entities
|
||||
HANGING_ENTITY(ENTITY, null),
|
||||
LEASH_KNOT(HANGING_ENTITY),
|
||||
PAINTING(HANGING_ENTITY),
|
||||
ITEM_FRAME(HANGING_ENTITY),
|
||||
GLOW_ITEM_FRAME(ITEM_FRAME),
|
||||
|
||||
// Projectiles
|
||||
PROJECTILE(ENTITY, null),
|
||||
ITEM_PROJECTILE(PROJECTILE, null),
|
||||
SNOWBALL(ITEM_PROJECTILE),
|
||||
ENDER_PEARL(ITEM_PROJECTILE),
|
||||
EGG(ITEM_PROJECTILE),
|
||||
POTION(ITEM_PROJECTILE),
|
||||
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
|
||||
FIREWORK_ROCKET(PROJECTILE),
|
||||
LLAMA_SPIT(PROJECTILE),
|
||||
SHULKER_BULLET(PROJECTILE),
|
||||
FISHING_BOBBER(PROJECTILE),
|
||||
WITHER_SKULL(PROJECTILE),
|
||||
DRAGON_FIREBALL(PROJECTILE), // Doesn't actually inherit fireball
|
||||
|
||||
ABSTRACT_ARROW(PROJECTILE, null),
|
||||
ARROW(ABSTRACT_ARROW),
|
||||
SPECTRAL_ARROW(ABSTRACT_ARROW),
|
||||
TRIDENT(ABSTRACT_ARROW),
|
||||
|
||||
ABSTRACT_FIREBALL(ENTITY, null),
|
||||
FIREBALL(ABSTRACT_FIREBALL),
|
||||
SMALL_FIREBALL(ABSTRACT_FIREBALL),
|
||||
|
||||
ABSTRACT_WIND_CHARGE(PROJECTILE, null),
|
||||
WIND_CHARGE(ABSTRACT_WIND_CHARGE),
|
||||
BREEZE_WIND_CHARGE(ABSTRACT_WIND_CHARGE),
|
||||
|
||||
// Vehicles
|
||||
VEHICLE(ENTITY, null),
|
||||
|
||||
ABSTRACT_MINECART(VEHICLE, null),
|
||||
MINECART(ABSTRACT_MINECART),
|
||||
FURNACE_MINECART(ABSTRACT_MINECART),
|
||||
COMMAND_BLOCK_MINECART(ABSTRACT_MINECART),
|
||||
TNT_MINECART(ABSTRACT_MINECART),
|
||||
SPAWNER_MINECART(ABSTRACT_MINECART),
|
||||
|
||||
ABSTRACT_MINECART_CONTAINER(ABSTRACT_MINECART, null),
|
||||
CHEST_MINECART(ABSTRACT_MINECART_CONTAINER),
|
||||
HOPPER_MINECART(ABSTRACT_MINECART_CONTAINER),
|
||||
|
||||
ABSTRACT_BOAT(VEHICLE, null),
|
||||
ABSTRACT_CHEST_BOAT(ABSTRACT_BOAT, null),
|
||||
ACACIA_BOAT(ABSTRACT_BOAT),
|
||||
ACACIA_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
BAMBOO_CHEST_RAFT(ABSTRACT_CHEST_BOAT),
|
||||
BAMBOO_RAFT(ABSTRACT_BOAT),
|
||||
BIRCH_BOAT(ABSTRACT_BOAT),
|
||||
BIRCH_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
CHERRY_BOAT(ABSTRACT_BOAT),
|
||||
CHERRY_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
DARK_OAK_BOAT(ABSTRACT_BOAT),
|
||||
DARK_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
JUNGLE_BOAT(ABSTRACT_BOAT),
|
||||
JUNGLE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
MANGROVE_BOAT(ABSTRACT_BOAT),
|
||||
MANGROVE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
OAK_BOAT(ABSTRACT_BOAT),
|
||||
OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
PALE_OAK_BOAT(ABSTRACT_BOAT),
|
||||
PALE_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
SPRUCE_BOAT(ABSTRACT_BOAT),
|
||||
SPRUCE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
|
||||
// Living entities as a larger subclass
|
||||
LIVING_ENTITY(ENTITY, null),
|
||||
ARMOR_STAND(LIVING_ENTITY),
|
||||
PLAYER(LIVING_ENTITY),
|
||||
|
||||
// Mobs as a larger subclass
|
||||
MOB(LIVING_ENTITY, null),
|
||||
ENDER_DRAGON(MOB),
|
||||
|
||||
SLIME(MOB),
|
||||
MAGMA_CUBE(SLIME),
|
||||
|
||||
// Ambient mobs
|
||||
AMBIENT_CREATURE(MOB, null),
|
||||
BAT(AMBIENT_CREATURE),
|
||||
|
||||
// Flying mobs
|
||||
FLYING_MOB(MOB, null),
|
||||
GHAST(FLYING_MOB),
|
||||
PHANTOM(FLYING_MOB),
|
||||
|
||||
// Pathfinder mobs and its subclasses
|
||||
PATHFINDER_MOB(MOB, null),
|
||||
ALLAY(PATHFINDER_MOB),
|
||||
|
||||
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
|
||||
SNOW_GOLEM(ABSTRACT_GOLEM),
|
||||
IRON_GOLEM(ABSTRACT_GOLEM),
|
||||
SHULKER(ABSTRACT_GOLEM),
|
||||
|
||||
// Ageable mobs and (tamable) animals
|
||||
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
|
||||
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
|
||||
VILLAGER(ABSTRACT_VILLAGER),
|
||||
WANDERING_TRADER(ABSTRACT_VILLAGER),
|
||||
|
||||
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
|
||||
AXOLOTL(ABSTRACT_ANIMAL),
|
||||
CHICKEN(ABSTRACT_ANIMAL),
|
||||
PANDA(ABSTRACT_ANIMAL),
|
||||
PIG(ABSTRACT_ANIMAL),
|
||||
POLAR_BEAR(ABSTRACT_ANIMAL),
|
||||
RABBIT(ABSTRACT_ANIMAL),
|
||||
SHEEP(ABSTRACT_ANIMAL),
|
||||
BEE(ABSTRACT_ANIMAL),
|
||||
TURTLE(ABSTRACT_ANIMAL),
|
||||
FOX(ABSTRACT_ANIMAL),
|
||||
FROG(ABSTRACT_ANIMAL),
|
||||
GOAT(ABSTRACT_ANIMAL),
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
|
||||
HORSE(ABSTRACT_HORSE),
|
||||
SKELETON_HORSE(ABSTRACT_HORSE),
|
||||
ZOMBIE_HORSE(ABSTRACT_HORSE),
|
||||
CAMEL(ABSTRACT_HORSE),
|
||||
|
||||
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
|
||||
DONKEY(ABSTRACT_CHESTED_HORSE),
|
||||
MULE(ABSTRACT_CHESTED_HORSE),
|
||||
LLAMA(ABSTRACT_CHESTED_HORSE),
|
||||
TRADER_LLAMA(LLAMA),
|
||||
|
||||
// Monsters
|
||||
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
|
||||
BLAZE(ABSTRACT_MONSTER),
|
||||
CREEPER(ABSTRACT_MONSTER),
|
||||
ENDERMITE(ABSTRACT_MONSTER),
|
||||
ENDERMAN(ABSTRACT_MONSTER),
|
||||
GIANT(ABSTRACT_MONSTER),
|
||||
SILVERFISH(ABSTRACT_MONSTER),
|
||||
VEX(ABSTRACT_MONSTER),
|
||||
WITHER(ABSTRACT_MONSTER),
|
||||
BREEZE(ABSTRACT_MONSTER),
|
||||
ZOGLIN(ABSTRACT_MONSTER),
|
||||
WARDEN(ABSTRACT_MONSTER),
|
||||
CREAKING(ABSTRACT_MONSTER),
|
||||
|
||||
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
|
||||
SKELETON(ABSTRACT_SKELETON),
|
||||
STRAY(ABSTRACT_SKELETON),
|
||||
WITHER_SKELETON(ABSTRACT_SKELETON),
|
||||
BOGGED(ABSTRACT_SKELETON),
|
||||
|
||||
ZOMBIE(ABSTRACT_MONSTER),
|
||||
DROWNED(ZOMBIE),
|
||||
HUSK(ZOMBIE),
|
||||
ZOMBIFIED_PIGLIN(ZOMBIE),
|
||||
ZOMBIE_VILLAGER(ZOMBIE),
|
||||
|
||||
GUARDIAN(ABSTRACT_MONSTER),
|
||||
ELDER_GUARDIAN(GUARDIAN),
|
||||
|
||||
SPIDER(ABSTRACT_MONSTER),
|
||||
CAVE_SPIDER(SPIDER),
|
||||
|
||||
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
|
||||
PIGLIN(ABSTRACT_PIGLIN),
|
||||
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
|
||||
|
||||
// Water mobs
|
||||
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
|
||||
DOLPHIN(AGEABLE_WATER_CREATURE),
|
||||
|
||||
SQUID(AGEABLE_WATER_CREATURE),
|
||||
GLOW_SQUID(SQUID),
|
||||
|
||||
WATER_ANIMAL(PATHFINDER_MOB, null),
|
||||
ABSTRACT_FISH(WATER_ANIMAL, null),
|
||||
PUFFERFISH(ABSTRACT_FISH),
|
||||
TADPOLE(ABSTRACT_FISH),
|
||||
|
||||
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
|
||||
COD(ABSTRACT_SCHOOLING_FISH),
|
||||
SALMON(ABSTRACT_SCHOOLING_FISH),
|
||||
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
|
||||
|
||||
// Raiders
|
||||
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
|
||||
WITCH(ABSTRACT_RAIDER),
|
||||
RAVAGER(ABSTRACT_RAIDER),
|
||||
|
||||
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
|
||||
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
|
||||
VINDICATOR(ABSTRACT_ILLAGER),
|
||||
PILLAGER(ABSTRACT_ILLAGER),
|
||||
EVOKER(SPELLCASTER_ILLAGER),
|
||||
ILLUSIONER(SPELLCASTER_ILLAGER);
|
||||
|
||||
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
|
||||
private final EntityType parent;
|
||||
private final String identifier;
|
||||
private int id = -1;
|
||||
|
||||
EntityTypes1_21_4(final EntityType parent) {
|
||||
this.parent = parent;
|
||||
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
EntityTypes1_21_4(final EntityType parent, @Nullable final String identifier) {
|
||||
this.parent = parent;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
if (id == -1) {
|
||||
throw new IllegalStateException("Ids have not been initialized yet (type " + name() + ")");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifier() {
|
||||
Preconditions.checkArgument(identifier != null, "Called identifier method on abstract type");
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable EntityType getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAbstractType() {
|
||||
return identifier == null;
|
||||
}
|
||||
|
||||
public static EntityType getTypeFromId(final int typeId) {
|
||||
return EntityTypeUtil.getTypeFromId(TYPES, typeId, ENTITY);
|
||||
}
|
||||
|
||||
public static void initialize(final Protocol<?, ?, ?, ?> protocol) {
|
||||
EntityTypeUtil.initialize(values(), TYPES, protocol, (type, id) -> type.id = id);
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,10 @@ import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern, boolean showInTooltip) {
|
||||
|
||||
public static final Type<ArmorTrim> TYPE = new Type<>(ArmorTrim.class) {
|
||||
public static final Type<ArmorTrim> TYPE1_20_5 = new Type<>(ArmorTrim.class) {
|
||||
@Override
|
||||
public ArmorTrim read(final ByteBuf buffer) {
|
||||
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE.read(buffer);
|
||||
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_20_5.read(buffer);
|
||||
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
|
||||
final boolean showInTooltip = buffer.readBoolean();
|
||||
return new ArmorTrim(material, pattern, showInTooltip);
|
||||
@@ -40,7 +40,39 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final ArmorTrim value) {
|
||||
ArmorTrimMaterial.TYPE.write(buffer, value.material);
|
||||
ArmorTrimMaterial.TYPE1_20_5.write(buffer, value.material);
|
||||
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
|
||||
buffer.writeBoolean(value.showInTooltip);
|
||||
}
|
||||
};
|
||||
public static final Type<ArmorTrim> TYPE1_21_2 = new Type<>(ArmorTrim.class) {
|
||||
@Override
|
||||
public ArmorTrim read(final ByteBuf buffer) {
|
||||
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_2.read(buffer);
|
||||
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
|
||||
final boolean showInTooltip = buffer.readBoolean();
|
||||
return new ArmorTrim(material, pattern, showInTooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final ArmorTrim value) {
|
||||
ArmorTrimMaterial.TYPE1_21_2.write(buffer, value.material);
|
||||
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
|
||||
buffer.writeBoolean(value.showInTooltip);
|
||||
}
|
||||
};
|
||||
public static final Type<ArmorTrim> TYPE1_21_4 = new Type<>(ArmorTrim.class) {
|
||||
@Override
|
||||
public ArmorTrim read(final ByteBuf buffer) {
|
||||
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_4.read(buffer);
|
||||
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
|
||||
final boolean showInTooltip = buffer.readBoolean();
|
||||
return new ArmorTrim(material, pattern, showInTooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final ArmorTrim value) {
|
||||
ArmorTrimMaterial.TYPE1_21_4.write(buffer, value.material);
|
||||
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
|
||||
buffer.writeBoolean(value.showInTooltip);
|
||||
}
|
||||
|
||||
+81
-7
@@ -27,13 +27,19 @@ import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.misc.HolderType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
import java.util.Map;
|
||||
|
||||
public record ArmorTrimMaterial(String assetName, int itemId, float itemModelIndex,
|
||||
Int2ObjectMap<String> overrideArmorMaterials, Tag description) {
|
||||
Map<String, String> overrideArmorMaterials, Tag description) {
|
||||
|
||||
public static final HolderType<ArmorTrimMaterial> TYPE = new HolderType<>() {
|
||||
public ArmorTrimMaterial(final String assetName, final int itemId, final Map<String, String> overrideArmorMaterials, final Tag description) {
|
||||
this(assetName, itemId, 0F, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
public static final HolderType<ArmorTrimMaterial> TYPE1_20_5 = new HolderType<>() {
|
||||
// The override key is an int, but given we don't use it at all and that creating a new type is annoying,
|
||||
// we'll just store it in the string map:tm:
|
||||
@Override
|
||||
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
|
||||
final String assetName = Types.STRING.read(buffer);
|
||||
@@ -41,10 +47,45 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
|
||||
final float itemModelIndex = buffer.readFloat();
|
||||
|
||||
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
|
||||
final Int2ObjectMap<String> overrideArmorMaterials = new Int2ObjectOpenHashMap<>(overrideArmorMaterialsSize);
|
||||
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
|
||||
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
|
||||
final int key = Types.VAR_INT.readPrimitive(buffer);
|
||||
final String value = Types.STRING.read(buffer);
|
||||
overrideArmorMaterials.put(Integer.toString(key), value);
|
||||
}
|
||||
|
||||
final Tag description = Types.TAG.read(buffer);
|
||||
return new ArmorTrimMaterial(assetName, item, itemModelIndex, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
|
||||
Types.STRING.write(buffer, value.assetName());
|
||||
Types.VAR_INT.writePrimitive(buffer, value.itemId());
|
||||
buffer.writeFloat(value.itemModelIndex());
|
||||
|
||||
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
|
||||
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
|
||||
Types.VAR_INT.writePrimitive(buffer, Integer.parseInt(entry.getKey()));
|
||||
Types.STRING.write(buffer, entry.getValue());
|
||||
}
|
||||
|
||||
Types.TAG.write(buffer, value.description());
|
||||
}
|
||||
};
|
||||
|
||||
public static final HolderType<ArmorTrimMaterial> TYPE1_21_2 = new HolderType<>() {
|
||||
@Override
|
||||
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
|
||||
final String assetName = Types.STRING.read(buffer);
|
||||
final int item = Types.VAR_INT.readPrimitive(buffer);
|
||||
final float itemModelIndex = buffer.readFloat();
|
||||
|
||||
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
|
||||
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
|
||||
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
|
||||
final String key = Types.STRING.read(buffer);
|
||||
final String value = Types.STRING.read(buffer);
|
||||
overrideArmorMaterials.put(key, value);
|
||||
}
|
||||
|
||||
@@ -59,8 +100,41 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
|
||||
buffer.writeFloat(value.itemModelIndex());
|
||||
|
||||
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
|
||||
for (final Int2ObjectMap.Entry<String> entry : value.overrideArmorMaterials().int2ObjectEntrySet()) {
|
||||
Types.VAR_INT.writePrimitive(buffer, entry.getIntKey());
|
||||
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
|
||||
Types.STRING.write(buffer, entry.getKey());
|
||||
Types.STRING.write(buffer, entry.getValue());
|
||||
}
|
||||
|
||||
Types.TAG.write(buffer, value.description());
|
||||
}
|
||||
};
|
||||
|
||||
public static final HolderType<ArmorTrimMaterial> TYPE1_21_4 = new HolderType<>() {
|
||||
@Override
|
||||
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
|
||||
final String assetName = Types.STRING.read(buffer);
|
||||
final int item = Types.VAR_INT.readPrimitive(buffer);
|
||||
|
||||
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
|
||||
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
|
||||
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
|
||||
final String key = Types.STRING.read(buffer);
|
||||
final String value = Types.STRING.read(buffer);
|
||||
overrideArmorMaterials.put(key, value);
|
||||
}
|
||||
|
||||
final Tag description = Types.TAG.read(buffer);
|
||||
return new ArmorTrimMaterial(assetName, item, overrideArmorMaterials, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
|
||||
Types.STRING.write(buffer, value.assetName());
|
||||
Types.VAR_INT.writePrimitive(buffer, value.itemId());
|
||||
|
||||
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
|
||||
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
|
||||
Types.STRING.write(buffer, entry.getKey());
|
||||
Types.STRING.write(buffer, entry.getValue());
|
||||
}
|
||||
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[] strings, int[] colors) {
|
||||
|
||||
public static final Type<CustomModelData1_21_4> TYPE = new Type<>(CustomModelData1_21_4.class) {
|
||||
@Override
|
||||
public CustomModelData1_21_4 read(final ByteBuf buffer) {
|
||||
final float[] floats = Types.FLOAT_ARRAY_PRIMITIVE.read(buffer);
|
||||
final boolean[] booleans = Types.BOOLEAN_ARRAY_PRIMITIVE.read(buffer);
|
||||
final String[] strings = Types.STRING_ARRAY.read(buffer);
|
||||
final int[] colors = Types.INT_ARRAY_PRIMITIVE.read(buffer);
|
||||
return new CustomModelData1_21_4(floats, booleans, strings, colors);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final CustomModelData1_21_4 value) {
|
||||
Types.FLOAT_ARRAY_PRIMITIVE.write(buffer, value.floats());
|
||||
Types.BOOLEAN_ARRAY_PRIMITIVE.write(buffer, value.booleans());
|
||||
Types.STRING_ARRAY.write(buffer, value.strings());
|
||||
Types.INT_ARRAY_PRIMITIVE.write(buffer, value.colors());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Null
|
||||
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
|
||||
final String model = Types.OPTIONAL_STRING.read(buffer);
|
||||
final String cameraOverlay = Types.OPTIONAL_STRING.read(buffer);
|
||||
final HolderSet allowedEntities = Types.HOLDER_SET.read(buffer);
|
||||
final HolderSet allowedEntities = Types.OPTIONAL_HOLDER_SET.read(buffer);
|
||||
final boolean dispensable = buffer.readBoolean();
|
||||
final boolean swappable = buffer.readBoolean();
|
||||
final boolean damageOnHurt = buffer.readBoolean();
|
||||
@@ -55,7 +55,7 @@ public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Null
|
||||
Types.SOUND_EVENT.write(buffer, value.soundEvent());
|
||||
Types.OPTIONAL_STRING.write(buffer, value.model());
|
||||
Types.OPTIONAL_STRING.write(buffer, value.cameraOverlay());
|
||||
Types.HOLDER_SET.write(buffer, value.allowedEntities());
|
||||
Types.OPTIONAL_HOLDER_SET.write(buffer, value.allowedEntities());
|
||||
buffer.writeBoolean(value.dispensable());
|
||||
buffer.writeBoolean(value.swappable());
|
||||
buffer.writeBoolean(value.damageOnHurt());
|
||||
|
||||
+2
-1
@@ -28,9 +28,10 @@ import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record FoodProperties1_20_5(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
|
||||
Item usingConvertsTo, FoodEffect[] possibleEffects) {
|
||||
@Nullable Item usingConvertsTo, FoodEffect[] possibleEffects) {
|
||||
|
||||
public static final Type<FoodProperties1_20_5> TYPE1_20_5 = new Type<>(FoodProperties1_20_5.class) {
|
||||
@Override
|
||||
|
||||
@@ -87,6 +87,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||
public static final ProtocolVersion v1_20_5 = register(766, "1.20.5-1.20.6", new SubVersionRange("1.20", 5, 6));
|
||||
public static final ProtocolVersion v1_21 = register(767, "1.21-1.21.1", new SubVersionRange("1.21", 0, 1));
|
||||
public static final ProtocolVersion v1_21_2 = register(768, "1.21.2-1.21.3", new SubVersionRange("1.21", 2, 3));
|
||||
public static final ProtocolVersion v1_21_4 = register(769, "1.21.4");
|
||||
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
|
||||
|
||||
static {
|
||||
|
||||
@@ -45,12 +45,14 @@ import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
|
||||
import com.viaversion.viaversion.api.minecraft.ChunkPosition;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.BitSetType;
|
||||
import com.viaversion.viaversion.api.type.types.BooleanArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.BooleanType;
|
||||
import com.viaversion.viaversion.api.type.types.ByteArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.ByteType;
|
||||
import com.viaversion.viaversion.api.type.types.ComponentType;
|
||||
import com.viaversion.viaversion.api.type.types.DoubleType;
|
||||
import com.viaversion.viaversion.api.type.types.EmptyType;
|
||||
import com.viaversion.viaversion.api.type.types.FloatArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.FloatType;
|
||||
import com.viaversion.viaversion.api.type.types.IntArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.IntType;
|
||||
@@ -115,14 +117,17 @@ public final class Types {
|
||||
public static final Type<byte[]> OPTIONAL_BYTE_ARRAY_PRIMITIVE = new ByteArrayType.OptionalByteArrayType();
|
||||
public static final Type<byte[]> SHORT_BYTE_ARRAY = new ShortByteArrayType();
|
||||
public static final Type<byte[]> REMAINING_BYTES = new RemainingBytesType();
|
||||
public static final Type<int[]> INT_ARRAY_PRIMITIVE = new IntArrayType();
|
||||
|
||||
public static final ShortType SHORT = new ShortType();
|
||||
public static final UnsignedShortType UNSIGNED_SHORT = new UnsignedShortType();
|
||||
|
||||
public static final IntType INT = new IntType();
|
||||
public static final Type<int[]> INT_ARRAY_PRIMITIVE = new IntArrayType();
|
||||
|
||||
public static final FloatType FLOAT = new FloatType();
|
||||
public static final FloatType.OptionalFloatType OPTIONAL_FLOAT = new FloatType.OptionalFloatType();
|
||||
public static final Type<float[]> FLOAT_ARRAY_PRIMITIVE = new FloatArrayType();
|
||||
|
||||
public static final DoubleType DOUBLE = new DoubleType();
|
||||
|
||||
public static final LongType LONG = new LongType();
|
||||
@@ -130,6 +135,7 @@ public final class Types {
|
||||
|
||||
public static final BooleanType BOOLEAN = new BooleanType();
|
||||
public static final BooleanType.OptionalBooleanType OPTIONAL_BOOLEAN = new BooleanType.OptionalBooleanType();
|
||||
public static final Type<boolean[]> BOOLEAN_ARRAY_PRIMITIVE = new BooleanArrayType();
|
||||
|
||||
/* Other Types */
|
||||
public static final Type<JsonElement> COMPONENT = new ComponentType();
|
||||
@@ -149,6 +155,8 @@ public final class Types {
|
||||
public static final VarLongType VAR_LONG = new VarLongType();
|
||||
|
||||
/* MC Types */
|
||||
public static final Type<byte[]> SERVERBOUND_CUSTOM_PAYLOAD_DATA = new RemainingBytesType(Short.MAX_VALUE);
|
||||
|
||||
public static final Type<BlockPosition> BLOCK_POSITION1_8 = new BlockPositionType1_8();
|
||||
public static final Type<BlockPosition> OPTIONAL_POSITION1_8 = new BlockPositionType1_8.OptionalBlockPositionType();
|
||||
public static final Type<BlockPosition> BLOCK_POSITION1_14 = new BlockPositionType1_14();
|
||||
@@ -191,6 +199,7 @@ public final class Types {
|
||||
|
||||
public static final BitSetType PROFILE_ACTIONS_ENUM1_19_3 = new BitSetType(6);
|
||||
public static final BitSetType PROFILE_ACTIONS_ENUM1_21_2 = new BitSetType(7);
|
||||
public static final BitSetType PROFILE_ACTIONS_ENUM1_21_4 = new BitSetType(8);
|
||||
|
||||
public static final ByteArrayType SIGNATURE_BYTES = new ByteArrayType(256);
|
||||
public static final BitSetType ACKNOWLEDGED_BIT_SET = new BitSetType(20);
|
||||
|
||||
@@ -26,13 +26,22 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ArrayType<T> extends Type<T[]> {
|
||||
private final Type<T> elementType;
|
||||
private final int maxLength;
|
||||
|
||||
public ArrayType(Type<T> type) {
|
||||
this(type, -1);
|
||||
}
|
||||
|
||||
public ArrayType(Type<T> type, int maxLength) {
|
||||
//noinspection unchecked
|
||||
super(type.getTypeName() + " Array", (Class<T[]>) getArrayClass(type.getOutputClass()));
|
||||
this.elementType = type;
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
public static Class<?> getArrayClass(Class<?> componentType) {
|
||||
@@ -43,16 +52,40 @@ public class ArrayType<T> extends Type<T[]> {
|
||||
@Override
|
||||
public T[] read(ByteBuf buffer) {
|
||||
int amount = Types.VAR_INT.readPrimitive(buffer);
|
||||
T[] array = (T[]) Array.newInstance(elementType.getOutputClass(), amount);
|
||||
if (maxLength != -1 && amount > maxLength) {
|
||||
throw new IllegalArgumentException("Array length " + amount + " is longer than maximum " + maxLength);
|
||||
}
|
||||
|
||||
for (int i = 0; i < amount; i++) {
|
||||
return amount < Short.MAX_VALUE ? readArray(buffer, amount) : readList(buffer, amount);
|
||||
}
|
||||
|
||||
private T[] readArray(ByteBuf buffer, int length) {
|
||||
T[] array = createArray(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
array[i] = elementType.read(buffer);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
private T[] readList(ByteBuf buffer, int length) {
|
||||
List<T> list = new ArrayList<>();
|
||||
for (int i = 0; i < length; i++) {
|
||||
list.add(elementType.read(buffer));
|
||||
}
|
||||
return list.toArray(createArray(0));
|
||||
}
|
||||
|
||||
private T[] createArray(int length) {
|
||||
//noinspection unchecked
|
||||
return (T[]) Array.newInstance(elementType.getOutputClass(), length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, T[] object) {
|
||||
if (maxLength != -1 && object.length > maxLength) {
|
||||
throw new IllegalArgumentException("Array length " + object.length + " is longer than maximum " + maxLength);
|
||||
}
|
||||
|
||||
Types.VAR_INT.writePrimitive(buffer, object.length);
|
||||
for (T o : object) {
|
||||
elementType.write(buffer, o);
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
// Ok...
|
||||
public class BooleanArrayType extends Type<boolean[]> {
|
||||
|
||||
private final int length;
|
||||
|
||||
public BooleanArrayType(final int length) {
|
||||
super(boolean[].class);
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public BooleanArrayType() {
|
||||
super(boolean[].class);
|
||||
this.length = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final boolean[] object) {
|
||||
if (this.length != -1) {
|
||||
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
|
||||
} else {
|
||||
Types.VAR_INT.writePrimitive(buffer, object.length);
|
||||
}
|
||||
for (final boolean b : object) {
|
||||
buffer.writeBoolean(b);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] read(final ByteBuf buffer) {
|
||||
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
|
||||
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
|
||||
final boolean[] array = new boolean[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
array[i] = buffer.readBoolean();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class FloatArrayType extends Type<float[]> {
|
||||
|
||||
private final int length;
|
||||
|
||||
public FloatArrayType(final int length) {
|
||||
super(float[].class);
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public FloatArrayType() {
|
||||
super(float[].class);
|
||||
this.length = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final float[] object) {
|
||||
if (this.length != -1) {
|
||||
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
|
||||
} else {
|
||||
Types.VAR_INT.writePrimitive(buffer, object.length);
|
||||
}
|
||||
for (final float f : object) {
|
||||
buffer.writeFloat(f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float[] read(final ByteBuf buffer) {
|
||||
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
|
||||
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
|
||||
final float[] array = new float[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
array[i] = buffer.readFloat();
|
||||
}
|
||||
return array;
|
||||
}
|
||||
}
|
||||
@@ -26,19 +26,35 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public class RemainingBytesType extends Type<byte[]> {
|
||||
private final int maxLength;
|
||||
|
||||
public RemainingBytesType() {
|
||||
this(-1);
|
||||
}
|
||||
|
||||
public RemainingBytesType(final int maxLength) {
|
||||
super(byte[].class);
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] read(ByteBuf buffer) {
|
||||
byte[] array = new byte[buffer.readableBytes()];
|
||||
public byte[] read(final ByteBuf buffer) {
|
||||
final int bytes = buffer.readableBytes();
|
||||
if (maxLength != -1 && bytes > maxLength) {
|
||||
throw new RuntimeException("Remaining bytes cannot be longer than " + maxLength + " (got " + bytes + ")");
|
||||
}
|
||||
|
||||
final byte[] array = new byte[bytes];
|
||||
buffer.readBytes(array);
|
||||
return array;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, byte[] object) {
|
||||
public void write(final ByteBuf buffer, final byte[] object) {
|
||||
if (maxLength != -1 && object.length > maxLength) {
|
||||
throw new RuntimeException("Remaining bytes cannot be longer than " + maxLength + " (got " + object.length + ")");
|
||||
}
|
||||
|
||||
buffer.writeBytes(object);
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,15 @@ public class VarIntType extends Type<Integer> implements TypeConverter<Integer>
|
||||
private static final int VALUE_BITS = 0x7F;
|
||||
private static final int MULTI_BYTE_BITS = ~VALUE_BITS;
|
||||
private static final int MAX_BYTES = 5;
|
||||
private static final int[] VAR_INT_LENGTHS = new int[65];
|
||||
|
||||
static {
|
||||
// Copied from Velocity https://github.com/PaperMC/Velocity/blob/08a42b3723633ea5eb6b96c0bb42180f3c2b07eb/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java#L166
|
||||
for (int i = 0; i <= 32; ++i) {
|
||||
VAR_INT_LENGTHS[i] = (int) Math.ceil((31d - (i - 1)) / 7d);
|
||||
}
|
||||
VAR_INT_LENGTHS[32] = 1; // Special case for the number 0.
|
||||
}
|
||||
|
||||
public VarIntType() {
|
||||
super("VarInt", Integer.class);
|
||||
@@ -88,4 +97,8 @@ public class VarIntType extends Type<Integer> implements TypeConverter<Integer>
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
public static int varIntLength(final int value) {
|
||||
return VAR_INT_LENGTHS[Integer.numberOfLeadingZeros(value)];
|
||||
}
|
||||
}
|
||||
+11
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.chunk;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
@@ -54,4 +55,14 @@ public final class ChunkSectionType1_18 extends Type<ChunkSection> {
|
||||
blockPaletteType.write(buffer, section.palette(PaletteType.BLOCKS));
|
||||
biomePaletteType.write(buffer, section.palette(PaletteType.BIOMES));
|
||||
}
|
||||
|
||||
public int serializedSize(final Chunk chunk) {
|
||||
int length = 0;
|
||||
for (final ChunkSection section : chunk.getSections()) {
|
||||
length += Short.BYTES
|
||||
+ blockPaletteType.serializedSize(section.palette(PaletteType.BLOCKS))
|
||||
+ biomePaletteType.serializedSize(section.palette(PaletteType.BIOMES));
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
+6
-17
@@ -52,14 +52,10 @@ public final class ChunkType1_18 extends Type<Chunk> {
|
||||
final CompoundTag heightMap = Types.NAMED_COMPOUND_TAG.read(buffer);
|
||||
|
||||
// Read sections
|
||||
final ByteBuf sectionsBuf = buffer.readBytes(Types.VAR_INT.readPrimitive(buffer));
|
||||
final ByteBuf sectionsBuf = buffer.readSlice(Types.VAR_INT.readPrimitive(buffer));
|
||||
final ChunkSection[] sections = new ChunkSection[ySectionCount];
|
||||
try {
|
||||
for (int i = 0; i < ySectionCount; i++) {
|
||||
sections[i] = sectionType.read(sectionsBuf);
|
||||
}
|
||||
} finally {
|
||||
sectionsBuf.release();
|
||||
for (int i = 0; i < ySectionCount; i++) {
|
||||
sections[i] = sectionType.read(sectionsBuf);
|
||||
}
|
||||
|
||||
final int blockEntitiesLength = Types.VAR_INT.readPrimitive(buffer);
|
||||
@@ -78,16 +74,9 @@ public final class ChunkType1_18 extends Type<Chunk> {
|
||||
|
||||
Types.NAMED_COMPOUND_TAG.write(buffer, chunk.getHeightMap());
|
||||
|
||||
final ByteBuf sectionBuffer = buffer.alloc().buffer();
|
||||
try {
|
||||
for (final ChunkSection section : chunk.getSections()) {
|
||||
sectionType.write(sectionBuffer, section);
|
||||
}
|
||||
sectionBuffer.readerIndex(0);
|
||||
Types.VAR_INT.writePrimitive(buffer, sectionBuffer.readableBytes());
|
||||
buffer.writeBytes(sectionBuffer);
|
||||
} finally {
|
||||
sectionBuffer.release(); // release buffer
|
||||
Types.VAR_INT.writePrimitive(buffer, sectionType.serializedSize(chunk));
|
||||
for (final ChunkSection section : chunk.getSections()) {
|
||||
sectionType.write(buffer, section);
|
||||
}
|
||||
|
||||
Types.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());
|
||||
|
||||
+6
-17
@@ -52,14 +52,10 @@ public final class ChunkType1_20_2 extends Type<Chunk> {
|
||||
final CompoundTag heightMap = Types.COMPOUND_TAG.read(buffer);
|
||||
|
||||
// Read sections
|
||||
final ByteBuf sectionsBuf = buffer.readBytes(Types.VAR_INT.readPrimitive(buffer));
|
||||
final ByteBuf sectionsBuf = buffer.readSlice(Types.VAR_INT.readPrimitive(buffer));
|
||||
final ChunkSection[] sections = new ChunkSection[ySectionCount];
|
||||
try {
|
||||
for (int i = 0; i < ySectionCount; i++) {
|
||||
sections[i] = sectionType.read(sectionsBuf);
|
||||
}
|
||||
} finally {
|
||||
sectionsBuf.release();
|
||||
for (int i = 0; i < ySectionCount; i++) {
|
||||
sections[i] = sectionType.read(sectionsBuf);
|
||||
}
|
||||
|
||||
final int blockEntitiesLength = Types.VAR_INT.readPrimitive(buffer);
|
||||
@@ -78,16 +74,9 @@ public final class ChunkType1_20_2 extends Type<Chunk> {
|
||||
|
||||
Types.COMPOUND_TAG.write(buffer, chunk.getHeightMap());
|
||||
|
||||
final ByteBuf sectionBuffer = buffer.alloc().buffer();
|
||||
try {
|
||||
for (final ChunkSection section : chunk.getSections()) {
|
||||
sectionType.write(sectionBuffer, section);
|
||||
}
|
||||
sectionBuffer.readerIndex(0);
|
||||
Types.VAR_INT.writePrimitive(buffer, sectionBuffer.readableBytes());
|
||||
buffer.writeBytes(sectionBuffer);
|
||||
} finally {
|
||||
sectionBuffer.release(); // release buffer
|
||||
Types.VAR_INT.writePrimitive(buffer, sectionType.serializedSize(chunk));
|
||||
for (final ChunkSection section : chunk.getSections()) {
|
||||
sectionType.write(buffer, section);
|
||||
}
|
||||
|
||||
Types.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());
|
||||
|
||||
+37
-7
@@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.minecraft.chunks.DataPaletteImpl;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.VarIntType;
|
||||
import com.viaversion.viaversion.util.CompactArrayUtil;
|
||||
import com.viaversion.viaversion.util.MathUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
@@ -94,13 +95,7 @@ public final class PaletteType1_18 extends Type<DataPalette> {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1, 2, and 3 bit linear block palettes can't be read by the client
|
||||
final int min = type == PaletteType.BLOCKS ? 4 : 1;
|
||||
int bitsPerValue = Math.max(min, MathUtil.ceilLog2(size));
|
||||
if (bitsPerValue > type.highestBitsPerValue()) {
|
||||
bitsPerValue = globalPaletteBits;
|
||||
}
|
||||
|
||||
final int bitsPerValue = bitsPerValue(size);
|
||||
buffer.writeByte(bitsPerValue);
|
||||
|
||||
if (bitsPerValue != globalPaletteBits) {
|
||||
@@ -113,4 +108,39 @@ public final class PaletteType1_18 extends Type<DataPalette> {
|
||||
|
||||
Types.LONG_ARRAY_PRIMITIVE.write(buffer, CompactArrayUtil.createCompactArrayWithPadding(bitsPerValue, type.size(), bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt));
|
||||
}
|
||||
|
||||
private int bitsPerValue(final int size) {
|
||||
// 1, 2, and 3 bit linear block palettes can't be read by the client
|
||||
final int min = type == PaletteType.BLOCKS ? 4 : 1;
|
||||
int bitsPerValue = Math.max(min, MathUtil.ceilLog2(size));
|
||||
if (bitsPerValue > type.highestBitsPerValue()) {
|
||||
bitsPerValue = globalPaletteBits;
|
||||
}
|
||||
return bitsPerValue;
|
||||
}
|
||||
|
||||
public int serializedSize(final DataPalette palette) {
|
||||
// This is a bit of extra work, but worth it to avoid otherwise having to allocate and write to an extra buffer.
|
||||
// On top of saving memory, it provides small but measurable speedup compared to writing to a separate buffer and then back
|
||||
final int size = palette.size();
|
||||
final int bitsPerValue = bitsPerValue(size);
|
||||
int serializedTypesSize = 0;
|
||||
int serializedValuesSize = 1; // At least one byte for 0 length
|
||||
if (size == 1) {
|
||||
serializedTypesSize = VarIntType.varIntLength(palette.idByIndex(0));
|
||||
} else {
|
||||
if (bitsPerValue != globalPaletteBits) {
|
||||
serializedTypesSize = VarIntType.varIntLength(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
serializedTypesSize += VarIntType.varIntLength(palette.idByIndex(i));
|
||||
}
|
||||
}
|
||||
|
||||
final int valuesPerLong = 64 / bitsPerValue;
|
||||
final int values = (type.size() + valuesPerLong - 1) / valuesPerLong;
|
||||
serializedValuesSize = VarIntType.varIntLength(values) + (Long.BYTES * values);
|
||||
}
|
||||
|
||||
return Byte.BYTES + serializedTypesSize + serializedValuesSize;
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class ItemType1_20_5 extends Type<Item> {
|
||||
return new Reference2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
final Map<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>();
|
||||
final Map<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>(Math.min(valuesSize + markersSize, 128));
|
||||
for (int i = 0; i < valuesSize; i++) {
|
||||
final StructuredData<?> value = dataType.read(buffer);
|
||||
final StructuredDataKey<?> key = dataType.key(value.id());
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
@@ -148,12 +147,19 @@ public class ParticleType extends DynamicType<Particle> {
|
||||
public static final DataReader<Particle> COLOR = (buf, particle) -> {
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf));
|
||||
};
|
||||
public static final DataReader<Particle> TRAIL = (buf, particle) -> {
|
||||
public static final DataReader<Particle> TRAIL1_21_2 = (buf, particle) -> {
|
||||
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target X
|
||||
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Y
|
||||
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Z
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // Color
|
||||
};
|
||||
public static final DataReader<Particle> TRAIL1_21_4 = (buf, particle) -> {
|
||||
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target X
|
||||
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Y
|
||||
particle.add(Types.DOUBLE, Types.DOUBLE.readPrimitive(buf)); // Target Z
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // Color
|
||||
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Duration
|
||||
};
|
||||
|
||||
public static DataReader<Particle> item(Type<Item> item) {
|
||||
return (buf, particle) -> particle.add(item, item.read(buf));
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.version;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
|
||||
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType;
|
||||
import com.viaversion.viaversion.api.type.types.item.ItemCostType1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.item.ItemType1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.item.StructuredDataType;
|
||||
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
|
||||
import java.util.List;
|
||||
|
||||
// Most of these are only safe to use after protocol loading
|
||||
public final class Types1_21_4 {
|
||||
|
||||
public static final StructuredDataType STRUCTURED_DATA = new StructuredDataType();
|
||||
public static final Type<StructuredData<?>[]> STRUCTURED_DATA_ARRAY = new ArrayType<>(STRUCTURED_DATA);
|
||||
public static final ItemType1_20_5 ITEM = new ItemType1_20_5(STRUCTURED_DATA);
|
||||
public static final Type<Item[]> ITEM_ARRAY = new ArrayType<>(ITEM);
|
||||
public static final Type<Item> ITEM_COST = new ItemCostType1_20_5(STRUCTURED_DATA_ARRAY);
|
||||
public static final Type<Item> OPTIONAL_ITEM_COST = new ItemCostType1_20_5.OptionalItemCostType(ITEM_COST);
|
||||
|
||||
public static final ParticleType PARTICLE = new ParticleType();
|
||||
public static final ArrayType<Particle> PARTICLES = new ArrayType<>(PARTICLE);
|
||||
public static final EntityDataTypes1_21 ENTITY_DATA_TYPES = new EntityDataTypes1_21(ITEM, PARTICLE, PARTICLES);
|
||||
public static final Type<EntityData> ENTITY_DATA = new EntityDataType(ENTITY_DATA_TYPES);
|
||||
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
|
||||
}
|
||||
@@ -22,11 +22,13 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.exception;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class InformativeException extends RuntimeException {
|
||||
private static final int MAX_MESSAGE_LENGTH = 5_000;
|
||||
private final List<DataEntry> dataEntries = new ArrayList<>();
|
||||
private boolean shouldBePrinted = true;
|
||||
private int sources;
|
||||
@@ -58,14 +60,21 @@ public class InformativeException extends RuntimeException {
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
StringBuilder builder = new StringBuilder("Please report this on the Via support Discord or open an issue on the relevant GitHub repository\n");
|
||||
final StringBuilder builder = new StringBuilder("Please report this on the Via support Discord or open an issue on the relevant GitHub repository\n");
|
||||
boolean first = true;
|
||||
for (DataEntry entry : dataEntries) {
|
||||
for (final DataEntry entry : dataEntries) {
|
||||
if (!first) {
|
||||
builder.append(", ");
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
builder.append(entry.name()).append(": ").append(entry.value());
|
||||
first = false;
|
||||
|
||||
builder.append(entry.name()).append(": ");
|
||||
String s = String.valueOf(entry.value());
|
||||
if (!Via.getManager().isDebug() && s.length() > 10 && builder.length() + s.length() > MAX_MESSAGE_LENGTH) {
|
||||
s = s.substring(0, MAX_MESSAGE_LENGTH - builder.length()) + "...";
|
||||
}
|
||||
builder.append(s.replaceAll("\\s", ""));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.util;
|
||||
|
||||
public final class Limit {
|
||||
|
||||
public static int max(final int value, final int max) {
|
||||
if (value > max) {
|
||||
throw new IllegalArgumentException("Value " + value + " is higher than the maximum " + max);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
fun Project.latestCommitHash(): String {
|
||||
return runGitCommand(listOf("rev-parse", "--short", "HEAD"))
|
||||
@@ -16,12 +15,9 @@ fun Project.branchName(): String {
|
||||
}
|
||||
|
||||
fun Project.runGitCommand(args: List<String>): String {
|
||||
val byteOut = ByteArrayOutputStream()
|
||||
exec {
|
||||
return providers.exec {
|
||||
commandLine = listOf("git") + args
|
||||
standardOutput = byteOut
|
||||
}
|
||||
return byteOut.toString(Charsets.UTF_8.name()).trim()
|
||||
}.standardOutput.asBytes.get().toString(Charsets.UTF_8).trim()
|
||||
}
|
||||
|
||||
fun JavaPluginExtension.javaTarget(version: Int) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
`java-library`
|
||||
`jvm-test-suite`
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
+2
-2
@@ -16,10 +16,10 @@ val main = setOf(
|
||||
projects.viaversionBukkit,
|
||||
projects.viaversionVelocity,
|
||||
projects.viaversionFabric
|
||||
).map { it.dependencyProject }
|
||||
).map { it.path }
|
||||
|
||||
subprojects {
|
||||
when (this) {
|
||||
when (path) {
|
||||
in main -> plugins.apply("via.shadow-conventions")
|
||||
else -> plugins.apply("via.base-conventions")
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.viaversion.viaversion.bukkit.platform.BukkitViaInjector;
|
||||
import com.viaversion.viaversion.bukkit.platform.BukkitViaLoader;
|
||||
import com.viaversion.viaversion.bukkit.platform.BukkitViaTask;
|
||||
import com.viaversion.viaversion.bukkit.platform.BukkitViaTaskTask;
|
||||
import com.viaversion.viaversion.bukkit.platform.FoliaViaTask;
|
||||
import com.viaversion.viaversion.bukkit.platform.PaperViaInjector;
|
||||
import com.viaversion.viaversion.dump.PluginInfo;
|
||||
import com.viaversion.viaversion.unsupported.UnsupportedPlugin;
|
||||
@@ -171,11 +172,18 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaPlatform<Player>
|
||||
|
||||
@Override
|
||||
public PlatformTask runSync(Runnable runnable, long delay) {
|
||||
if (FOLIA) {
|
||||
// Set the delayed tick to at least 1, as Folia requires this.
|
||||
return new FoliaViaTask(getServer().getGlobalRegionScheduler().runDelayed(this, (e) -> runnable.run(), delay <= 0L ? 1L : delay));
|
||||
}
|
||||
return new BukkitViaTask(getServer().getScheduler().runTaskLater(this, runnable, delay));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformTask runRepeatingSync(Runnable runnable, long period) {
|
||||
if (FOLIA) {
|
||||
return new FoliaViaTask(getServer().getGlobalRegionScheduler().runAtFixedRate(this, (e) -> runnable.run(), 1, period));
|
||||
}
|
||||
return new BukkitViaTask(getServer().getScheduler().runTaskTimer(this, runnable, 0, period));
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -22,6 +22,7 @@ import com.viaversion.viaversion.bukkit.util.NMSUtil;
|
||||
import com.viaversion.viaversion.exception.CancelCodecException;
|
||||
import com.viaversion.viaversion.exception.CancelDecoderException;
|
||||
import com.viaversion.viaversion.exception.InformativeException;
|
||||
import com.viaversion.viaversion.util.ByteBufUtil;
|
||||
import com.viaversion.viaversion.util.PipelineUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
@@ -39,7 +40,7 @@ public final class BukkitDecodeHandler extends MessageToMessageDecoder<ByteBuf>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) throws Exception {
|
||||
protected void decode(final ChannelHandlerContext ctx, final ByteBuf bytebuf, final List<Object> out) {
|
||||
if (!connection.checkServerboundPacket()) {
|
||||
throw CancelDecoderException.generate(null);
|
||||
}
|
||||
@@ -48,7 +49,7 @@ public final class BukkitDecodeHandler extends MessageToMessageDecoder<ByteBuf>
|
||||
return;
|
||||
}
|
||||
|
||||
final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
|
||||
final ByteBuf transformedBuf = ByteBufUtil.copy(ctx.alloc(), bytebuf);
|
||||
try {
|
||||
connection.transformIncoming(transformedBuf, CancelDecoderException::generate);
|
||||
out.add(transformedBuf.retain());
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ import com.viaversion.viaversion.bukkit.util.NMSUtil;
|
||||
import com.viaversion.viaversion.exception.CancelCodecException;
|
||||
import com.viaversion.viaversion.exception.CancelEncoderException;
|
||||
import com.viaversion.viaversion.exception.InformativeException;
|
||||
import com.viaversion.viaversion.util.ByteBufUtil;
|
||||
import com.viaversion.viaversion.util.PipelineUtil;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
@@ -52,7 +53,7 @@ public final class BukkitEncodeHandler extends MessageToMessageEncoder<ByteBuf>
|
||||
return;
|
||||
}
|
||||
|
||||
final ByteBuf transformedBuf = ctx.alloc().buffer().writeBytes(bytebuf);
|
||||
final ByteBuf transformedBuf = ByteBufUtil.copy(ctx.alloc(), bytebuf);
|
||||
try {
|
||||
final boolean needsCompression = !handledCompression && handleCompressionOrder(ctx, transformedBuf);
|
||||
connection.transformClientbound(transformedBuf, CancelEncoderException::generate);
|
||||
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21;
|
||||
|
||||
import com.viaversion.viaversion.ViaVersionPlugin;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.block.BlockDamageEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
public class LegacyChangeItemListener extends PlayerChangeItemListener {
|
||||
|
||||
public LegacyChangeItemListener(final ViaVersionPlugin plugin) {
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onBlockDamageEvent(final BlockDamageEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final ItemStack item = event.getItemInHand();
|
||||
sendAttributeUpdate(player, item, Slot.HAND);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void onInventoryClose(final InventoryCloseEvent event) {
|
||||
if (event.getPlayer() instanceof Player player &&
|
||||
(event.getInventory().getType() == InventoryType.CRAFTING ||
|
||||
event.getInventory().getType() == InventoryType.PLAYER)) {
|
||||
sendArmorUpdate(player);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendArmorUpdate(final Player player) {
|
||||
final UserConnection connection = getUserConnection(player);
|
||||
final EfficiencyAttributeStorage storage = getEfficiencyStorage(connection);
|
||||
if (storage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PlayerInventory inventory = player.getInventory();
|
||||
final ItemStack helmet = inventory.getHelmet();
|
||||
final ItemStack leggings = swiftSneak != null ? inventory.getLeggings() : null;
|
||||
final ItemStack boots = depthStrider != null ? inventory.getBoots() : null;
|
||||
|
||||
storage.setEnchants(player.getEntityId(), connection, storage.activeEnchants()
|
||||
.aquaAffinity(helmet != null ? helmet.getEnchantmentLevel(aquaAffinity) : 0)
|
||||
.swiftSneak(leggings != null ? leggings.getEnchantmentLevel(swiftSneak) : 0)
|
||||
.depthStrider(boots != null ? boots.getEnchantmentLevel(depthStrider) : 0));
|
||||
}
|
||||
|
||||
}
|
||||
+23
-33
@@ -18,7 +18,6 @@
|
||||
package com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21;
|
||||
|
||||
import com.viaversion.viaversion.ViaVersionPlugin;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
|
||||
@@ -38,11 +37,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
public class PlayerChangeItemListener extends ViaBukkitListener {
|
||||
|
||||
// Use legacy function and names here to support all versions
|
||||
private final Enchantment efficiency = getByName("efficiency", "DIG_SPEED");
|
||||
private final Enchantment aquaAffinity = getByName("aqua_affinity", "WATER_WORKER");
|
||||
private final Enchantment depthStrider = getByName("depth_strider", "DEPTH_STRIDER");
|
||||
private final Enchantment soulSpeed = getByName("soul_speed", "SOUL_SPEED");
|
||||
private final Enchantment swiftSneak = getByName("swift_sneak", "SWIFT_SNEAK");
|
||||
protected final Enchantment efficiency = getByName("efficiency", "DIG_SPEED");
|
||||
protected final Enchantment aquaAffinity = getByName("aqua_affinity", "WATER_WORKER");
|
||||
protected final Enchantment depthStrider = getByName("depth_strider", "DEPTH_STRIDER");
|
||||
protected final Enchantment soulSpeed = getByName("soul_speed", "SOUL_SPEED");
|
||||
protected final Enchantment swiftSneak = getByName("swift_sneak", "SWIFT_SNEAK");
|
||||
|
||||
public PlayerChangeItemListener(final ViaVersionPlugin plugin) {
|
||||
super(plugin, Protocol1_20_5To1_21.class);
|
||||
@@ -55,35 +54,26 @@ public class PlayerChangeItemListener extends ViaBukkitListener {
|
||||
sendAttributeUpdate(player, item, Slot.HAND);
|
||||
}
|
||||
|
||||
protected EfficiencyAttributeStorage getEfficiencyStorage(final UserConnection connection) {
|
||||
return connection != null ? connection.get(EfficiencyAttributeStorage.class) : null;
|
||||
}
|
||||
|
||||
void sendAttributeUpdate(final Player player, @Nullable final ItemStack item, final Slot slot) {
|
||||
final UserConnection connection = Via.getAPI().getConnection(player.getUniqueId());
|
||||
if (connection == null || !isOnPipe(player)) {
|
||||
return;
|
||||
}
|
||||
final UserConnection connection = getUserConnection(player);
|
||||
final EfficiencyAttributeStorage storage = getEfficiencyStorage(connection);
|
||||
if (storage == null) return;
|
||||
|
||||
final EfficiencyAttributeStorage storage = connection.get(EfficiencyAttributeStorage.class);
|
||||
if (storage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final EfficiencyAttributeStorage.ActiveEnchants activeEnchants = storage.activeEnchants();
|
||||
int efficiencyLevel = activeEnchants.efficiency().level();
|
||||
int aquaAffinityLevel = activeEnchants.aquaAffinity().level();
|
||||
int soulSpeedLevel = activeEnchants.soulSpeed().level();
|
||||
int swiftSneakLevel = activeEnchants.swiftSneak().level();
|
||||
int depthStriderLevel = activeEnchants.depthStrider().level();
|
||||
switch (slot) {
|
||||
case HAND -> efficiencyLevel = item != null ? item.getEnchantmentLevel(efficiency) : 0;
|
||||
case HELMET -> aquaAffinityLevel = item != null ? item.getEnchantmentLevel(aquaAffinity) : 0;
|
||||
case LEGGINGS -> swiftSneakLevel = item != null && swiftSneak != null ? item.getEnchantmentLevel(swiftSneak) : 0;
|
||||
case BOOTS -> {
|
||||
depthStriderLevel = item != null && depthStrider != null ? item.getEnchantmentLevel(depthStrider) : 0;
|
||||
// TODO This needs continuous ticking for the supporting block as a conditional effect
|
||||
// and is even more prone to desync from high ping than the other attributes
|
||||
//soulSpeedLevel = item != null && soulSpeed != null ? item.getEnchantmentLevel(soulSpeed) : 0;
|
||||
}
|
||||
}
|
||||
storage.setEnchants(player.getEntityId(), connection, efficiencyLevel, soulSpeedLevel, swiftSneakLevel, aquaAffinityLevel, depthStriderLevel);
|
||||
EfficiencyAttributeStorage.ActiveEnchants enchants = storage.activeEnchants();
|
||||
enchants = switch (slot) {
|
||||
case HAND -> enchants.efficiency(item != null ? item.getEnchantmentLevel(efficiency) : 0);
|
||||
case HELMET -> enchants.aquaAffinity(item != null ? item.getEnchantmentLevel(aquaAffinity) : 0);
|
||||
case LEGGINGS -> enchants.swiftSneak(item != null && swiftSneak != null ? item.getEnchantmentLevel(swiftSneak) : 0);
|
||||
case BOOTS -> enchants.depthStrider(item != null && depthStrider != null ? item.getEnchantmentLevel(depthStrider) : 0);
|
||||
// TODO This needs continuous ticking for the supporting block as a conditional effect
|
||||
// and is even more prone to desync from high ping than the other attributes
|
||||
//soulSpeedLevel = item != null && soulSpeed != null ? item.getEnchantmentLevel(soulSpeed) : 0;
|
||||
};
|
||||
storage.setEnchants(player.getEntityId(), connection, enchants);
|
||||
}
|
||||
|
||||
enum Slot {
|
||||
|
||||
+11
-4
@@ -26,23 +26,25 @@ import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.bukkit.listeners.UpdateListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.multiversion.PlayerSneakListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_14_4to1_15.EntityToggleGlideListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_19_3to1_19_4.ArmorToggleListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_18_2to1_19.BlockBreakListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_19_3to1_19_4.ArmorToggleListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.LegacyChangeItemListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PaperPlayerChangeItemListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.ArmorListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.BlockListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.DeathListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.HandItemCache;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_8to1_9.PaperPatch;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PaperPlayerChangeItemListener;
|
||||
import com.viaversion.viaversion.bukkit.listeners.v1_20_5to1_21.PlayerChangeItemListener;
|
||||
import com.viaversion.viaversion.bukkit.providers.BukkitAckSequenceProvider;
|
||||
import com.viaversion.viaversion.bukkit.providers.BukkitBlockConnectionProvider;
|
||||
import com.viaversion.viaversion.bukkit.providers.BukkitInventoryQuickMoveProvider;
|
||||
import com.viaversion.viaversion.bukkit.providers.BukkitPickItemProvider;
|
||||
import com.viaversion.viaversion.bukkit.providers.BukkitViaMovementTransmitter;
|
||||
import com.viaversion.viaversion.protocols.v1_11_1to1_12.provider.InventoryQuickMoveProvider;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.ConnectionData;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.providers.BlockConnectionProvider;
|
||||
import com.viaversion.viaversion.protocols.v1_18_2to1_19.provider.AckSequenceProvider;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.provider.PickItemProvider;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.HandItemProvider;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.MovementTransmitterProvider;
|
||||
import java.util.HashSet;
|
||||
@@ -184,7 +186,12 @@ public class BukkitViaLoader implements ViaPlatformLoader {
|
||||
if (PaperViaInjector.hasClass("io.papermc.paper.event.player.PlayerInventorySlotChangeEvent")) {
|
||||
new PaperPlayerChangeItemListener(plugin).register();
|
||||
} else {
|
||||
new PlayerChangeItemListener(plugin).register();
|
||||
new LegacyChangeItemListener(plugin).register();
|
||||
}
|
||||
}
|
||||
if (serverProtocolVersion.olderThan(ProtocolVersion.v1_21_4)) {
|
||||
if (PaperViaInjector.hasMethod(Material.class, "isItem")) {
|
||||
Via.getManager().getProviders().use(PickItemProvider.class, new BukkitPickItemProvider(plugin));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.bukkit.platform;
|
||||
|
||||
import com.viaversion.viaversion.api.platform.PlatformTask;
|
||||
import io.papermc.paper.threadedregions.scheduler.ScheduledTask;
|
||||
|
||||
public record FoliaViaTask(ScheduledTask task) implements PlatformTask<ScheduledTask> {
|
||||
@Override
|
||||
public void cancel() {
|
||||
task.cancel();
|
||||
}
|
||||
}
|
||||
+20
-12
@@ -65,12 +65,7 @@ public final class PaperViaInjector {
|
||||
}
|
||||
|
||||
private static boolean hasServerProtocolMethod() {
|
||||
try {
|
||||
Class.forName("org.bukkit.UnsafeValues").getDeclaredMethod("getProtocolVersion");
|
||||
return true;
|
||||
} catch (final ClassNotFoundException | NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
return hasMethod("org.bukkit.UnsafeValues", "getProtocolVersion");
|
||||
}
|
||||
|
||||
private static boolean hasPaperInjectionMethod() {
|
||||
@@ -78,12 +73,7 @@ public final class PaperViaInjector {
|
||||
}
|
||||
|
||||
private static boolean hasIsStoppingMethod() {
|
||||
try {
|
||||
Bukkit.class.getDeclaredMethod("isStopping");
|
||||
return true;
|
||||
} catch (final NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
return hasMethod(Bukkit.class, "isStopping");
|
||||
}
|
||||
|
||||
private static boolean hasPacketLimiter() {
|
||||
@@ -98,4 +88,22 @@ public final class PaperViaInjector {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasMethod(final String className, final String method) {
|
||||
try {
|
||||
Class.forName(className).getDeclaredMethod(method);
|
||||
return true;
|
||||
} catch (final ClassNotFoundException | NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasMethod(final Class<?> clazz, final String method) {
|
||||
try {
|
||||
clazz.getDeclaredMethod(method);
|
||||
return true;
|
||||
} catch (final NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.bukkit.providers;
|
||||
|
||||
import com.viaversion.viaversion.ViaVersionPlugin;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.bukkit.platform.PaperViaInjector;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.provider.PickItemProvider;
|
||||
import java.util.UUID;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemFactory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class BukkitPickItemProvider extends PickItemProvider {
|
||||
private static final boolean HAS_PLACEMENT_MATERIAL_METHOD = PaperViaInjector.hasMethod("org.bukkit.block.BlockData", "getPlacementMaterial");
|
||||
private static final boolean HAS_SPAWN_EGG_METHOD = PaperViaInjector.hasMethod(ItemFactory.class, "getSpawnEgg");
|
||||
private static final double BLOCK_RANGE = 4.5 + 1;
|
||||
private static final double BLOCK_RANGE_SQUARED = BLOCK_RANGE * BLOCK_RANGE;
|
||||
private static final double ENTITY_RANGE = 3 + 3;
|
||||
private final ViaVersionPlugin plugin;
|
||||
|
||||
public BukkitPickItemProvider(final ViaVersionPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pickItemFromBlock(final UserConnection connection, final BlockPosition blockPosition, final boolean includeData) {
|
||||
final UUID uuid = connection.getProtocolInfo().getUuid();
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
final Player player = plugin.getServer().getPlayer(uuid);
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Location playerLocation = player.getLocation();
|
||||
if (blockPosition.distanceFromCenterSquared(playerLocation.getX(), playerLocation.getY(), playerLocation.getZ()) > BLOCK_RANGE_SQUARED) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Block block = player.getWorld().getBlockAt(blockPosition.x(), blockPosition.y(), blockPosition.z());
|
||||
if (block.getType() == Material.AIR) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemStack item = blockToItem(block, includeData && player.getGameMode() == GameMode.CREATIVE);
|
||||
if (item != null) {
|
||||
pickItem(player, item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private @Nullable ItemStack blockToItem(final Block block, final boolean includeData) {
|
||||
if (HAS_PLACEMENT_MATERIAL_METHOD) {
|
||||
final ItemStack item = new ItemStack(block.getBlockData().getPlacementMaterial(), 1);
|
||||
if (includeData && item.getItemMeta() instanceof final BlockStateMeta blockStateMeta) {
|
||||
blockStateMeta.setBlockState(block.getState());
|
||||
}
|
||||
return item;
|
||||
} else if (block.getType().isItem()) {
|
||||
return new ItemStack(block.getType(), 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pickItemFromEntity(final UserConnection connection, final int entityId, final boolean includeData) {
|
||||
if (!HAS_SPAWN_EGG_METHOD) {
|
||||
return;
|
||||
}
|
||||
|
||||
final UUID uuid = connection.getProtocolInfo().getUuid();
|
||||
plugin.getServer().getScheduler().runTask(plugin, () -> {
|
||||
final Player player = plugin.getServer().getPlayer(uuid);
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Entity entity = player.getWorld().getNearbyEntities(player.getLocation(), ENTITY_RANGE, ENTITY_RANGE, ENTITY_RANGE).stream()
|
||||
.filter(e -> e.getEntityId() == entityId)
|
||||
.findAny()
|
||||
.orElse(null);
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Material spawnEggType = Bukkit.getItemFactory().getSpawnEgg(entity.getType());
|
||||
if (spawnEggType != null) {
|
||||
pickItem(player, new ItemStack(spawnEggType, 1));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void pickItem(final Player player, final ItemStack item) {
|
||||
// Find matching item
|
||||
final PlayerInventory inventory = player.getInventory();
|
||||
final ItemStack[] contents = inventory.getStorageContents();
|
||||
int sourceSlot = -1;
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
final ItemStack content = contents[i];
|
||||
if (content == null || !content.isSimilar(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sourceSlot = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sourceSlot != -1) {
|
||||
moveToHotbar(inventory, sourceSlot, contents);
|
||||
} else if (player.getGameMode() == GameMode.CREATIVE) {
|
||||
spawnItem(item, inventory, contents);
|
||||
}
|
||||
}
|
||||
|
||||
private void spawnItem(final ItemStack item, final PlayerInventory inventory, final ItemStack[] contents) {
|
||||
final int targetSlot = findEmptyHotbarSlot(inventory, inventory.getHeldItemSlot());
|
||||
inventory.setHeldItemSlot(targetSlot);
|
||||
final ItemStack heldItem = inventory.getItem(targetSlot);
|
||||
int emptySlot = targetSlot;
|
||||
if (heldItem != null && heldItem.getType() != Material.AIR) {
|
||||
// Swap to the first free slot in the inventory, else add it to the current hotbar slot
|
||||
for (int i = 0; i < contents.length; i++) {
|
||||
if (contents[i] == null || contents[i].getType() == Material.AIR) {
|
||||
emptySlot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inventory.setItem(emptySlot, heldItem);
|
||||
inventory.setItemInMainHand(item);
|
||||
}
|
||||
|
||||
private void moveToHotbar(final PlayerInventory inventory, final int sourceSlot, final ItemStack[] contents) {
|
||||
if (sourceSlot <= 9) {
|
||||
inventory.setHeldItemSlot(sourceSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
final int heldSlot = inventory.getHeldItemSlot();
|
||||
final int targetSlot = findEmptyHotbarSlot(inventory, heldSlot);
|
||||
inventory.setHeldItemSlot(targetSlot);
|
||||
final ItemStack heldItem = inventory.getItem(targetSlot);
|
||||
inventory.setItemInMainHand(contents[sourceSlot]);
|
||||
inventory.setItem(sourceSlot, heldItem);
|
||||
}
|
||||
|
||||
private int findEmptyHotbarSlot(final PlayerInventory inventory, final int heldSlot) {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
final ItemStack item = inventory.getItem(i);
|
||||
if (item == null || item.getType() == Material.AIR) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return heldSlot;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,10 @@ public abstract class ViaListener {
|
||||
* @return True if on pipe
|
||||
*/
|
||||
protected boolean isOnPipe(UUID uuid) {
|
||||
UserConnection userConnection = getUserConnection(uuid);
|
||||
return isOnPipe(getUserConnection(uuid));
|
||||
}
|
||||
|
||||
protected boolean isOnPipe(UserConnection userConnection) {
|
||||
return userConnection != null &&
|
||||
(requiredPipeline == null || userConnection.getProtocolInfo().getPipeline().contains(requiredPipeline));
|
||||
}
|
||||
|
||||
@@ -244,9 +244,12 @@ public class ViaManagerImpl implements ViaManager {
|
||||
}
|
||||
|
||||
if (version < 17) {
|
||||
platform.getLogger().warning("You are running an outdated Java version, please update it to at least Java 17 (your version is " + javaVersion + ").");
|
||||
platform.getLogger().warning("You are running an outdated Java version, please update it to at least Java 21 (your version is " + javaVersion + ").");
|
||||
platform.getLogger().warning("ViaVersion no longer officially supports this version of Java, only offering unsupported compatibility builds.");
|
||||
platform.getLogger().warning("See https://github.com/ViaVersion/ViaVersion/releases/tag/5.0.0 for more information.");
|
||||
} else if (version < 21) {
|
||||
platform.getLogger().warning("Please update your Java runtime to at least Java 21 (your version is " + javaVersion + ").");
|
||||
platform.getLogger().warning("At some point in the future, ViaVersion will no longer be compatible with this version of Java.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public class ReloadSubCmd implements ViaSubCommand {
|
||||
@Override
|
||||
public boolean execute(ViaCommandSender sender, String[] args) {
|
||||
Via.getManager().getConfigurationProvider().reloadConfigs();
|
||||
sendMessage(sender, "&6Configuration successfully reloaded! Some features may need a restart.");
|
||||
sendMessage(sender, "&6Configuration successfully reloaded! Some config options may require a restart to take effect.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,7 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
private boolean cancelBlockSounds;
|
||||
private boolean hideScoreboardNumbers;
|
||||
private boolean fix1_21PlacementRotation;
|
||||
private boolean swordBlockingViaConsumable;
|
||||
|
||||
protected AbstractViaConfig(final File configFile, final Logger logger) {
|
||||
super(configFile, logger);
|
||||
@@ -164,7 +165,8 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
handleInvalidItemCount = getBoolean("handle-invalid-item-count", false);
|
||||
cancelBlockSounds = getBoolean("cancel-block-sounds", true);
|
||||
hideScoreboardNumbers = getBoolean("hide-scoreboard-numbers", false);
|
||||
fix1_21PlacementRotation = getBoolean("fix-1_21-placement-rotation", false);
|
||||
fix1_21PlacementRotation = getBoolean("fix-1_21-placement-rotation", true);
|
||||
swordBlockingViaConsumable = getBoolean("sword-blocking-via-consumable", true);
|
||||
}
|
||||
|
||||
private BlockedProtocolVersions loadBlockedProtocolVersions() {
|
||||
@@ -556,4 +558,9 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
public boolean fix1_21PlacementRotation() {
|
||||
return fix1_21PlacementRotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean swordBlockingViaConsumable() {
|
||||
return swordBlockingViaConsumable;
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,8 @@ import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.VarIntType;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.exception.InformativeException;
|
||||
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
|
||||
@@ -55,6 +55,7 @@ import java.util.function.Function;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class UserConnectionImpl implements UserConnection {
|
||||
private static final int PASSTHROUGH_DATA_BYTES = Long.BYTES * 2 + 2;
|
||||
private static final AtomicLong IDS = new AtomicLong();
|
||||
private final long id = IDS.incrementAndGet();
|
||||
private final Map<Class<?>, StorableObject> storedObjects = new ConcurrentHashMap<>();
|
||||
@@ -244,7 +245,8 @@ public class UserConnectionImpl implements UserConnection {
|
||||
}
|
||||
|
||||
private void sendRawPacketToServerServerSide(final ByteBuf packet, final boolean currentThread) {
|
||||
final ByteBuf buf = packet.alloc().buffer();
|
||||
final int initialCapacity = active ? packet.readableBytes() + PASSTHROUGH_DATA_BYTES : packet.readableBytes();
|
||||
final ByteBuf buf = packet.alloc().buffer(initialCapacity);
|
||||
try {
|
||||
// We'll use passing through because there are some encoder wrappers
|
||||
ChannelHandlerContext context = PipelineUtil
|
||||
@@ -333,7 +335,7 @@ public class UserConnectionImpl implements UserConnection {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = Types.VAR_INT.readPrimitive(buf);
|
||||
final int id = Types.VAR_INT.readPrimitive(buf);
|
||||
if (id == PacketWrapper.PASSTHROUGH_ID) {
|
||||
if (!passthroughTokens.remove(Types.UUID.read(buf))) {
|
||||
throw new IllegalArgumentException("Invalid token");
|
||||
@@ -341,20 +343,47 @@ public class UserConnectionImpl implements UserConnection {
|
||||
return;
|
||||
}
|
||||
|
||||
PacketWrapper wrapper = new PacketWrapperImpl(id, buf, this);
|
||||
State state = protocolInfo.getState(direction);
|
||||
final int valuesReaderIndex = buf.readerIndex();
|
||||
final PacketWrapperImpl wrapper = new PacketWrapperImpl(id, buf, this);
|
||||
try {
|
||||
protocolInfo.getPipeline().transform(direction, state, wrapper);
|
||||
} catch (CancelException ex) {
|
||||
protocolInfo.getPipeline().transform(direction, protocolInfo.getState(direction), wrapper);
|
||||
} catch (final CancelException ex) {
|
||||
throw cancelSupplier.apply(ex);
|
||||
}
|
||||
|
||||
ByteBuf transformed = buf.alloc().buffer();
|
||||
writeToBuffer(wrapper, buf, id, valuesReaderIndex);
|
||||
}
|
||||
|
||||
private void writeToBuffer(final PacketWrapperImpl wrapper, final ByteBuf buf, final int originalId, final int originalReaderIndex) {
|
||||
final int remainingBytes = buf.readableBytes();
|
||||
if (buf.readerIndex() == originalReaderIndex && wrapper.areStoredPacketValuesEmpty()) {
|
||||
if (wrapper.getId() == originalId) {
|
||||
// No changes needed; just set the reader and writer indexes and we're done
|
||||
buf.setIndex(0, originalReaderIndex + remainingBytes);
|
||||
return;
|
||||
}
|
||||
if (VarIntType.varIntLength(wrapper.getId()) == VarIntType.varIntLength(originalId)) {
|
||||
// If the var int encoded length is the same, simply replace the id at the head
|
||||
buf.setIndex(0, 0);
|
||||
Types.VAR_INT.writePrimitive(buf, wrapper.getId());
|
||||
buf.writerIndex(originalReaderIndex + remainingBytes);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Instead of allocating a possible unnecessarily large buffer to write the wrapper contents to,
|
||||
// only allocate the remaining bytes and write the rest to the original buf's head directly.
|
||||
final ByteBuf remainingBuf = buf.alloc().buffer(remainingBytes, remainingBytes);
|
||||
try {
|
||||
wrapper.writeToBuffer(transformed);
|
||||
buf.clear().writeBytes(transformed);
|
||||
// Copy before modifying the buffer
|
||||
remainingBuf.writeBytes(buf, remainingBytes);
|
||||
|
||||
// Reset indexes, write wrapper contents, then the unread bytes
|
||||
buf.setIndex(0, 0);
|
||||
wrapper.writeProcessedValues(buf);
|
||||
buf.writeBytes(remainingBuf);
|
||||
} finally {
|
||||
transformed.release();
|
||||
remainingBuf.release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.Protocol1_20_3To1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.Protocol1_20To1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.Protocol1_21To1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.Protocol1_9_1To1_9_3;
|
||||
@@ -194,6 +195,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
|
||||
registerProtocol(new Protocol1_20_5To1_21(), ProtocolVersion.v1_21, ProtocolVersion.v1_20_5);
|
||||
registerProtocol(new Protocol1_21To1_21_2(), ProtocolVersion.v1_21_2, ProtocolVersion.v1_21);
|
||||
registerProtocol(new Protocol1_21_2To1_21_4(), ProtocolVersion.v1_21_4, ProtocolVersion.v1_21_2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+24
-11
@@ -222,6 +222,18 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
|
||||
@Override
|
||||
public void writeToBuffer(ByteBuf buffer) throws InformativeException {
|
||||
writeProcessedValues(buffer);
|
||||
if (inputBuffer != null) {
|
||||
buffer.writeBytes(inputBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean areStoredPacketValuesEmpty() {
|
||||
// Check for read/added packet values, not the input buffer
|
||||
return packetValues.isEmpty() && readableObjects.isEmpty();
|
||||
}
|
||||
|
||||
public void writeProcessedValues(ByteBuf buffer) throws InformativeException {
|
||||
if (id != -1) {
|
||||
Types.VAR_INT.writePrimitive(buffer, id);
|
||||
}
|
||||
@@ -238,7 +250,6 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
throw createInformativeException(e, packetValue.type(), i);
|
||||
}
|
||||
}
|
||||
writeRemaining(buffer);
|
||||
}
|
||||
|
||||
private InformativeException createInformativeException(final Exception cause, final Type<?> type, final int index) {
|
||||
@@ -264,12 +275,6 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
packetValues.clear();
|
||||
}
|
||||
|
||||
private void writeRemaining(ByteBuf output) {
|
||||
if (inputBuffer != null) {
|
||||
output.writeBytes(inputBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Class<? extends Protocol> protocol, boolean skipCurrentPipeline) throws InformativeException {
|
||||
send0(protocol, skipCurrentPipeline, true);
|
||||
@@ -320,7 +325,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
final ProtocolInfo protocolInfo = user().getProtocolInfo();
|
||||
final List<Protocol> protocols = protocolInfo.getPipeline().pipes(protocolClass, skipCurrentPipeline, direction);
|
||||
apply(direction, protocolInfo.getState(direction), protocols);
|
||||
final ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||
final ByteBuf output = allocateOutputBuffer();
|
||||
try {
|
||||
writeToBuffer(output);
|
||||
return output.retain();
|
||||
@@ -354,7 +359,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
return cancelledFuture();
|
||||
}
|
||||
|
||||
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||
ByteBuf output = allocateOutputBuffer();
|
||||
try {
|
||||
writeToBuffer(output);
|
||||
return user().sendRawPacketFuture(output.retain());
|
||||
@@ -373,7 +378,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||
ByteBuf output = allocateOutputBuffer();
|
||||
try {
|
||||
writeToBuffer(output);
|
||||
if (currentThread) {
|
||||
@@ -386,6 +391,14 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private ByteBuf allocateOutputBuffer() {
|
||||
if (inputBuffer == null) {
|
||||
return user().getChannel().alloc().buffer();
|
||||
}
|
||||
// May have already been partially or fully read
|
||||
return inputBuffer.alloc().buffer(Math.max(inputBuffer.readableBytes(), 256));
|
||||
}
|
||||
|
||||
private ChannelFuture cancelledFuture() {
|
||||
return user().getChannel().newFailedFuture(new RuntimeException("Tried to send cancelled packet"));
|
||||
}
|
||||
@@ -454,7 +467,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||
ByteBuf output = allocateOutputBuffer();
|
||||
try {
|
||||
writeToBuffer(output);
|
||||
if (currentThread) {
|
||||
|
||||
+33
-32
@@ -18,26 +18,26 @@
|
||||
package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
|
||||
// To replace if needed:
|
||||
// ChunkType1_20_2
|
||||
// RecipeRewriter1_20_3
|
||||
// Types1_21, Types1_OLD
|
||||
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_99To_98> {
|
||||
// RecipeDisplayRewriter
|
||||
// Types1_21_4, Types1_OLD
|
||||
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21_2, ServerboundPacket1_21_4, Protocol1_99To_98> {
|
||||
|
||||
public BlockItemPacketRewriter1_99(final Protocol1_99To_98 protocol) {
|
||||
super(protocol, Types1_21.ITEM, Types1_21.ITEM_ARRAY);
|
||||
super(protocol, Types1_21_4.ITEM, Types1_21_4.ITEM_ARRAY);
|
||||
/*super(protocol,
|
||||
Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY, Types1_21.ITEM, Types1_21.ITEM_ARRAY,
|
||||
Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST, Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST
|
||||
Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY, Types1_21_4.ITEM, Types1_21_4.ITEM_ARRAY,
|
||||
Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST, Types1_21_4.ITEM_COST, Types1_21_4.OPTIONAL_ITEM_COST
|
||||
);*/
|
||||
}
|
||||
|
||||
@@ -46,31 +46,32 @@ final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<Clientbou
|
||||
// Register block and block state id changes
|
||||
// Other places using block state id mappings: Spawn particle, entity data, entity spawn (falling blocks)
|
||||
// Tags and statistics use block (!) ids
|
||||
final BlockRewriter<ClientboundPacket1_21> blockRewriter = BlockRewriter.for1_20_2(protocol);
|
||||
blockRewriter.registerBlockEvent(ClientboundPackets1_21.BLOCK_EVENT);
|
||||
blockRewriter.registerBlockUpdate(ClientboundPackets1_21.BLOCK_UPDATE);
|
||||
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE);
|
||||
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21.LEVEL_EVENT, 2001);
|
||||
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
|
||||
blockRewriter.registerBlockEntityData(ClientboundPackets1_21.BLOCK_ENTITY_DATA);
|
||||
final BlockRewriter<ClientboundPacket1_21_2> blockRewriter = BlockRewriter.for1_20_2(protocol);
|
||||
blockRewriter.registerBlockEvent(ClientboundPackets1_21_2.BLOCK_EVENT);
|
||||
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_2.BLOCK_UPDATE);
|
||||
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_2.SECTION_BLOCKS_UPDATE);
|
||||
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_2.LEVEL_EVENT, 2001);
|
||||
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_2.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
|
||||
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_2.BLOCK_ENTITY_DATA);
|
||||
|
||||
// Registers item id changes
|
||||
// Other places using item ids are: Entity data, tags, statistics, effect
|
||||
// registerOpenScreen(ClientboundPackets1_21.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
|
||||
//protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
|
||||
registerCooldown1_21_2(ClientboundPackets1_21.COOLDOWN);
|
||||
registerSetContent1_21_2(ClientboundPackets1_21.CONTAINER_SET_CONTENT);
|
||||
registerSetSlot1_21_2(ClientboundPackets1_21.CONTAINER_SET_SLOT);
|
||||
registerAdvancements1_20_3(ClientboundPackets1_21.UPDATE_ADVANCEMENTS);
|
||||
registerSetEquipment(ClientboundPackets1_21.SET_EQUIPMENT);
|
||||
registerContainerClick1_21_2(ServerboundPackets1_20_5.CONTAINER_CLICK);
|
||||
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS);
|
||||
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
|
||||
// registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
|
||||
registerSetPlayerInventory(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY);
|
||||
registerCooldown1_21_2(ClientboundPackets1_21_2.COOLDOWN);
|
||||
registerSetContent1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT);
|
||||
registerSetSlot1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_SLOT);
|
||||
registerAdvancements1_20_3(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS);
|
||||
registerSetEquipment(ClientboundPackets1_21_2.SET_EQUIPMENT);
|
||||
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
|
||||
registerContainerClick1_21_2(ServerboundPackets1_21_4.CONTAINER_CLICK);
|
||||
registerSetCreativeModeSlot(ServerboundPackets1_21_4.SET_CREATIVE_MODE_SLOT);
|
||||
|
||||
final RecipeDisplayRewriter<ClientboundPacket1_21> recipeRewriter = new RecipeDisplayRewriter<>(protocol);
|
||||
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21.UPDATE_RECIPES);
|
||||
//recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21.RECIPE_BOOK_ADD);
|
||||
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21.PLACE_GHOST_RECIPE);
|
||||
final RecipeDisplayRewriter<ClientboundPacket1_21_2> recipeRewriter = new RecipeDisplayRewriter<>(protocol);
|
||||
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_2.UPDATE_RECIPES);
|
||||
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_2.RECIPE_BOOK_ADD);
|
||||
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE);
|
||||
// OR do this if serialization of recipes changed and override the relevant method
|
||||
// Add new serializers to RecipeDisplayRewriter, or extend the last one for changes
|
||||
}
|
||||
|
||||
+3
-3
@@ -19,11 +19,11 @@ package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.util.SerializerVersion;
|
||||
|
||||
public final class ComponentRewriter1_99 extends ComponentRewriter<ClientboundPacket1_21> {
|
||||
final class ComponentRewriter1_99 extends ComponentRewriter<ClientboundPacket1_21_2> {
|
||||
|
||||
public ComponentRewriter1_99(final Protocol1_99To_98 protocol) {
|
||||
super(protocol, ReadType.NBT);
|
||||
@@ -41,6 +41,6 @@ public final class ComponentRewriter1_99 extends ComponentRewriter<ClientboundPa
|
||||
|
||||
@Override
|
||||
protected SerializerVersion inputSerializerVersion() {
|
||||
return SerializerVersion.V1_20_5;
|
||||
return SerializerVersion.V1_21_4;
|
||||
}
|
||||
}
|
||||
+21
-21
@@ -18,19 +18,19 @@
|
||||
package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
|
||||
|
||||
// Replace if needed
|
||||
// Types1_OLD
|
||||
// Types1_21
|
||||
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21, Protocol1_99To_98> {
|
||||
// Types1_21_4
|
||||
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21_2, Protocol1_99To_98> {
|
||||
|
||||
public EntityPacketRewriter1_99(final Protocol1_99To_98 protocol) {
|
||||
super(protocol);
|
||||
@@ -39,14 +39,14 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
|
||||
@Override
|
||||
public void registerPackets() {
|
||||
// Tracks entities, applies entity data rewrites registered below, untracks entities
|
||||
registerTrackerWithData1_19(ClientboundPackets1_21.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets1_21.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_21.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
|
||||
registerRemoveEntities(ClientboundPackets1_21.REMOVE_ENTITIES);
|
||||
registerTrackerWithData1_19(ClientboundPackets1_21_2.ADD_ENTITY, EntityTypes1_21_4.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_21_4.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
|
||||
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
|
||||
|
||||
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
|
||||
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21.LOGIN, wrapper -> {
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
|
||||
final int entityId = wrapper.passthrough(Types.INT); // Entity id
|
||||
wrapper.passthrough(Types.BOOLEAN); // Hardcore
|
||||
wrapper.passthrough(Types.STRING_ARRAY); // World List
|
||||
@@ -64,7 +64,7 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
|
||||
trackPlayer(wrapper.user(), entityId);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21.RESPAWN, wrapper -> {
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.RESPAWN, wrapper -> {
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
|
||||
@@ -79,20 +79,20 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
|
||||
if (id >= SomeAddedIndex) {
|
||||
id++;
|
||||
}
|
||||
return Types1_21.ENTITY_DATA_TYPES.byId(id);
|
||||
return Types1_21_4.ENTITY_DATA_TYPES.byId(id);
|
||||
});*/
|
||||
|
||||
// Registers registry type id changes
|
||||
registerEntityDataTypeHandler(
|
||||
Types1_21.ENTITY_DATA_TYPES.itemType,
|
||||
Types1_21.ENTITY_DATA_TYPES.blockStateType,
|
||||
Types1_21.ENTITY_DATA_TYPES.optionalBlockStateType,
|
||||
Types1_21.ENTITY_DATA_TYPES.particleType,
|
||||
Types1_21.ENTITY_DATA_TYPES.particlesType,
|
||||
Types1_21.ENTITY_DATA_TYPES.componentType,
|
||||
Types1_21.ENTITY_DATA_TYPES.optionalComponentType
|
||||
Types1_21_4.ENTITY_DATA_TYPES.itemType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.blockStateType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.optionalBlockStateType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.particleType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.particlesType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.componentType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.optionalComponentType
|
||||
);
|
||||
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
|
||||
registerBlockStateHandler(EntityTypes1_21_4.ABSTRACT_MINECART, 11);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,6 +103,6 @@ final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_2
|
||||
|
||||
@Override
|
||||
public EntityType typeFromId(final int type) {
|
||||
return EntityTypes1_20_5.getTypeFromId(type);
|
||||
return EntityTypes1_21_4.getTypeFromId(type);
|
||||
}
|
||||
}
|
||||
+48
-48
@@ -20,20 +20,20 @@ package com.viaversion.viaversion.protocols.template;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.data.MappingDataBase;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.AttributeRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ParticleRewriter;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
|
||||
@@ -43,56 +43,56 @@ import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
|
||||
|
||||
// Placeholders to replace (in the entire package):
|
||||
// Protocol1_99To_98, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99 - move the latter two to a rewriter package
|
||||
// ClientboundPacket1_21
|
||||
// ServerboundPacket1_20_5
|
||||
// EntityTypes1_20_5 (MAPPED type)
|
||||
// Types1_21_2.PARTICLE
|
||||
// ClientboundPacket1_21_2
|
||||
// ServerboundPacket1_21_4
|
||||
// EntityTypes1_21_4 (MAPPED type)
|
||||
// Types1_21_4.PARTICLE
|
||||
// 1.99, 1.98
|
||||
final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
|
||||
final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_4, ServerboundPacket1_21_4> {
|
||||
|
||||
public static final MappingData MAPPINGS = new MappingDataBase("1.98", "1.99");
|
||||
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
|
||||
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
|
||||
private final ParticleRewriter<ClientboundPacket1_21> particleRewriter = new ParticleRewriter<>(this, /*Types1_OLD.PARTICLE,*/ Types1_21_2.PARTICLE);
|
||||
private final TagRewriter<ClientboundPacket1_21> tagRewriter = new TagRewriter<>(this);
|
||||
private final ComponentRewriter1_99 componentRewriter = new ComponentRewriter1_99(this);
|
||||
private final ParticleRewriter<ClientboundPacket1_21_2> particleRewriter = new ParticleRewriter<>(this, /*Types1_OLD.PARTICLE,*/ Types1_21_4.PARTICLE);
|
||||
private final TagRewriter<ClientboundPacket1_21_2> tagRewriter = new TagRewriter<>(this);
|
||||
private final ComponentRewriter<ClientboundPacket1_21_2> componentRewriter = new ComponentRewriter1_99(this);
|
||||
|
||||
public Protocol1_99To_98() {
|
||||
// Passing the class types into the super constructor is needed for automatic packet type id remapping, but can otherwise be omitted
|
||||
super(ClientboundPacket1_21.class, ClientboundPacket1_21.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
|
||||
super(ClientboundPacket1_21_2.class, ClientboundPacket1_21_2.class, ServerboundPacket1_21_4.class, ServerboundPacket1_21_4.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
super.registerPackets();
|
||||
|
||||
tagRewriter.registerGeneric(ClientboundPackets1_21.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundPackets1_21_2.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
|
||||
|
||||
// If needed for item or component changes
|
||||
componentRewriter.registerOpenScreen(ClientboundPackets1_21.OPEN_SCREEN);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SET_ACTION_BAR_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SET_TITLE_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SET_SUBTITLE_TEXT);
|
||||
componentRewriter.registerBossEvent(ClientboundPackets1_21.BOSS_EVENT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.DISCONNECT);
|
||||
componentRewriter.registerTabList(ClientboundPackets1_21.TAB_LIST);
|
||||
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21.PLAYER_COMBAT_KILL);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SYSTEM_CHAT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.DISGUISED_CHAT);
|
||||
componentRewriter.registerPlayerInfoUpdate1_21_2(ClientboundPackets1_21.PLAYER_INFO_UPDATE);
|
||||
componentRewriter.registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_ACTION_BAR_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_TITLE_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
|
||||
componentRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
|
||||
componentRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
|
||||
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISGUISED_CHAT);
|
||||
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE);
|
||||
componentRewriter.registerPing();
|
||||
|
||||
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
|
||||
particleRewriter.registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
|
||||
particleRewriter.registerExplode1_21_2(ClientboundPackets1_21.EXPLODE); // Rewrites the included sound and particles
|
||||
particleRewriter.registerLevelParticles1_20_5(ClientboundPackets1_21_2.LEVEL_PARTICLES);
|
||||
particleRewriter.registerExplode1_21_2(ClientboundPackets1_21_2.EXPLODE); // Rewrites the included sound and particles
|
||||
|
||||
final SoundRewriter<ClientboundPacket1_21> soundRewriter = new SoundRewriter<>(this);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND_ENTITY);
|
||||
final SoundRewriter<ClientboundPacket1_21_2> soundRewriter = new SoundRewriter<>(this);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND_ENTITY);
|
||||
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
|
||||
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21.UPDATE_ATTRIBUTES);
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_2.AWARD_STATS);
|
||||
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
|
||||
|
||||
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
|
||||
/*new CommandRewriter1_19_4<>(this) {
|
||||
@@ -105,16 +105,16 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
|
||||
super.handleArgument(wrapper, argumentType);
|
||||
}
|
||||
}
|
||||
}.registerDeclareCommands1_19(ClientboundPackets1_21.COMMANDS);*/
|
||||
}.registerDeclareCommands1_19(ClientboundPackets1_21_2.COMMANDS);*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMappingDataLoaded() {
|
||||
// Uncomment this if the entity types enum has been newly added specifically for this Protocol
|
||||
// EntityTypes1_20_5.initialize(this);
|
||||
// EntityTypes1_21_4.initialize(this);
|
||||
|
||||
// Uncomment if a new particle was added = ids shifted; requires a new Types_ class copied from the last
|
||||
/*Types1_21_2.PARTICLE.filler(this)
|
||||
/*Types1_21_4.PARTICLE.filler(this)
|
||||
.reader("block", ParticleType.Readers.BLOCK)
|
||||
.reader("block_marker", ParticleType.Readers.BLOCK)
|
||||
.reader("dust_pillar", ParticleType.Readers.BLOCK)
|
||||
@@ -126,7 +126,7 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
|
||||
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
|
||||
.reader("shriek", ParticleType.Readers.SHRIEK)
|
||||
.reader("entity_effect", ParticleType.Readers.COLOR)
|
||||
.reader("trail", ParticleType.Readers.TRAIL)
|
||||
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
|
||||
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));*/
|
||||
|
||||
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
|
||||
@@ -135,7 +135,7 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
|
||||
@Override
|
||||
public void init(final UserConnection connection) {
|
||||
// Register the entity tracker - used for entity id/entity data rewriting AND for tracking world data sent to the client (then used for chunk data rewriting)
|
||||
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
|
||||
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_4.PLAYER));
|
||||
}
|
||||
|
||||
// Overriding these four methods is important as they are relied on various rewriter classes
|
||||
@@ -156,27 +156,27 @@ final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, Cl
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParticleRewriter<ClientboundPacket1_21> getParticleRewriter() {
|
||||
public ParticleRewriter<ClientboundPacket1_21_2> getParticleRewriter() {
|
||||
return particleRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagRewriter<ClientboundPacket1_21> getTagRewriter() {
|
||||
public TagRewriter<ClientboundPacket1_21_2> getTagRewriter() {
|
||||
return tagRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentRewriter getComponentRewriter() {
|
||||
public ComponentRewriter<ClientboundPacket1_21_2> getComponentRewriter() {
|
||||
return componentRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PacketTypesProvider<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
|
||||
protected PacketTypesProvider<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_4, ServerboundPacket1_21_4> createPacketTypesProvider() {
|
||||
return new SimplePacketTypesProvider<>(
|
||||
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class),
|
||||
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
|
||||
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_4.class, ServerboundConfigurationPackets1_20_5.class),
|
||||
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_4.class, ServerboundConfigurationPackets1_20_5.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -132,13 +132,13 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
|
||||
if (effectID == 2002) {
|
||||
int data = packetWrapper.get(Types.INT, 1);
|
||||
boolean isInstant = false;
|
||||
Pair<Integer, Boolean> newData = PotionColorMappings1_11.getNewData(data);
|
||||
PotionColorMappings1_11.PotionData newData = PotionColorMappings1_11.getNewData(data);
|
||||
if (newData == null) {
|
||||
getLogger().warning("Received unknown potion data: " + data);
|
||||
data = 0;
|
||||
} else {
|
||||
data = newData.key();
|
||||
isInstant = newData.value();
|
||||
data = newData.data();
|
||||
isInstant = newData.instant();
|
||||
}
|
||||
if (isInstant) {
|
||||
packetWrapper.set(Types.INT, 0, 2007);
|
||||
|
||||
+6
-5
@@ -17,14 +17,13 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.v1_10to1_11.data;
|
||||
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class PotionColorMappings1_11 {
|
||||
|
||||
//<oldData> to <newData, isInstant> mapping
|
||||
private static final Int2ObjectMap<Pair<Integer, Boolean>> POTIONS = new Int2ObjectOpenHashMap<>(37);
|
||||
private static final Int2ObjectMap<PotionData> POTIONS = new Int2ObjectOpenHashMap<>(37);
|
||||
|
||||
static {
|
||||
addRewrite(0, 3694022, false);
|
||||
@@ -66,12 +65,14 @@ public class PotionColorMappings1_11 {
|
||||
addRewrite(36, 3381504, false);
|
||||
}
|
||||
|
||||
public static Pair<Integer, Boolean> getNewData(int oldData) {
|
||||
public static @Nullable PotionData getNewData(int oldData) {
|
||||
return POTIONS.get(oldData);
|
||||
}
|
||||
|
||||
private static void addRewrite(int oldData, int newData, boolean isInstant) {
|
||||
POTIONS.put(oldData, new Pair<>(newData, isInstant));
|
||||
POTIONS.put(oldData, new PotionData(newData, isInstant));
|
||||
}
|
||||
|
||||
public record PotionData(int data, boolean instant) {
|
||||
}
|
||||
}
|
||||
+17
-2
@@ -24,9 +24,9 @@ import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.item.DataItem;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_9;
|
||||
import com.viaversion.viaversion.api.minecraft.item.DataItem;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
@@ -37,6 +37,7 @@ import com.viaversion.viaversion.protocols.v1_10to1_11.data.EntityMappings1_11;
|
||||
import com.viaversion.viaversion.protocols.v1_10to1_11.storage.EntityTracker1_11;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
@@ -91,13 +92,27 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
|
||||
map(Types.INT); // 8 - Data
|
||||
|
||||
// Track Entity
|
||||
handler(objectTrackerHandler());
|
||||
handler(wrapper -> {
|
||||
byte type = wrapper.get(Types.BYTE, 0);
|
||||
if (type == EntityTypes1_10.ObjectType.FISHIHNG_HOOK.getId()) {
|
||||
tryFixFishingHookVelocity(wrapper);
|
||||
} else if (type == EntityTypes1_10.ObjectType.ITEM.getId()) {
|
||||
// Older clients used stone as fallback as long as the entity data was not set
|
||||
wrapper.send(Protocol1_10To1_11.class);
|
||||
wrapper.cancel();
|
||||
|
||||
final int entityId = wrapper.get(Types.VAR_INT, 0);
|
||||
|
||||
final List<EntityData> entityDataList = new ArrayList<>();
|
||||
entityDataList.add(new EntityData(6, EntityDataTypes1_9.ITEM, new DataItem(1, (byte) 1, null)));
|
||||
|
||||
final PacketWrapper setItem = PacketWrapper.create(ClientboundPackets1_9_3.SET_ENTITY_DATA, wrapper.user());
|
||||
setItem.write(Types.VAR_INT, entityId);
|
||||
setItem.write(Types1_9.ENTITY_DATA_LIST, entityDataList);
|
||||
setItem.send(Protocol1_10To1_11.class);
|
||||
}
|
||||
});
|
||||
handler(objectTrackerHandler());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+14
-5
@@ -166,8 +166,8 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, tag.getValue().clone());
|
||||
}
|
||||
});
|
||||
if (w.user().getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_2)) {
|
||||
// Make sure it's included in the configuration packets
|
||||
if (w.user().getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_5)) {
|
||||
// Make sure it's included in the configuration packets as it may already be required for registry data
|
||||
tagsPacket.send(Protocol1_12_2To1_13.class);
|
||||
} else {
|
||||
tagsPacket.scheduleSend(Protocol1_12_2To1_13.class);
|
||||
@@ -775,7 +775,10 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
for (Item[] ingredient : recipe.ingredients()) {
|
||||
Item[] clone = new Item[ingredient.length];
|
||||
for (int i = 0; i < ingredient.length; i++) {
|
||||
if (clone[i] == null) continue;
|
||||
if (ingredient[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clone[i] = ingredient[i].copy();
|
||||
}
|
||||
recipesPacket.write(Types.ITEM1_13_ARRAY, clone);
|
||||
@@ -789,7 +792,10 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
for (Item[] ingredient : recipe.ingredients()) {
|
||||
Item[] clone = new Item[ingredient.length];
|
||||
for (int i = 0; i < ingredient.length; i++) {
|
||||
if (clone[i] == null) continue;
|
||||
if (ingredient[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
clone[i] = ingredient[i].copy();
|
||||
}
|
||||
recipesPacket.write(Types.ITEM1_13_ARRAY, clone);
|
||||
@@ -800,7 +806,10 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
recipesPacket.write(Types.STRING, recipe.group());
|
||||
Item[] ingredient = new Item[recipe.ingredient().length];
|
||||
for (int i = 0; i < ingredient.length; i++) {
|
||||
if (recipe.ingredient()[i] == null) continue;
|
||||
if (recipe.ingredient()[i] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ingredient[i] = recipe.ingredient()[i].copy();
|
||||
}
|
||||
recipesPacket.write(Types.ITEM1_13_ARRAY, ingredient);
|
||||
|
||||
+31
-25
@@ -18,16 +18,19 @@
|
||||
package com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.blockentities;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.NumberTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.BlockEntityProvider;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class FlowerPotHandler implements BlockEntityProvider.BlockEntityHandler {
|
||||
// Object -> string (id without namespace) or byte (numeric id)
|
||||
private static final Map<Pair<?, Byte>, Integer> flowers = new HashMap<>();
|
||||
private static final int EMPTY_POT = 5265;
|
||||
private static final Map<String, Byte> STRING_TO_BYTE_ID = new HashMap<>();
|
||||
private static final Map<IntIdPair, Integer> FLOWERS = new HashMap<>();
|
||||
|
||||
static {
|
||||
register("air", (byte) 0, (byte) 0, 5265);
|
||||
@@ -55,37 +58,40 @@ public class FlowerPotHandler implements BlockEntityProvider.BlockEntityHandler
|
||||
|
||||
}
|
||||
|
||||
public static void register(String identifier, byte numbericBlockId, byte blockData, int newId) {
|
||||
flowers.put(new Pair<>(identifier, blockData), newId);
|
||||
flowers.put(new Pair<>(numbericBlockId, blockData), newId);
|
||||
private static void register(String identifier, byte blockId, byte blockData, int newId) {
|
||||
STRING_TO_BYTE_ID.put(identifier, blockId);
|
||||
FLOWERS.put(new IntIdPair(blockId, blockData), newId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int transform(UserConnection user, CompoundTag tag) {
|
||||
Object item = tag.contains("Item") ? tag.get("Item").getValue() : null;
|
||||
Object data = tag.contains("Data") ? tag.get("Data").getValue() : null;
|
||||
|
||||
// Convert item to String without namespace or to Byte
|
||||
if (item instanceof String) {
|
||||
item = Key.stripMinecraftNamespace((String) item);
|
||||
} else if (item instanceof Number) {
|
||||
item = ((Number) item).byteValue();
|
||||
} else {
|
||||
item = (byte) 0;
|
||||
Tag itemTag = tag.get("Item");
|
||||
byte item = 0;
|
||||
if (itemTag instanceof StringTag stringTag) {
|
||||
item = STRING_TO_BYTE_ID.getOrDefault(Key.stripMinecraftNamespace(stringTag.getValue()), (byte) 0);
|
||||
} else if (itemTag instanceof NumberTag numberTag) {
|
||||
item = numberTag.asByte();
|
||||
}
|
||||
|
||||
// Convert data to Byte
|
||||
if (data instanceof Number) {
|
||||
data = ((Number) data).byteValue();
|
||||
} else {
|
||||
data = (byte) 0;
|
||||
byte data = 0;
|
||||
if (tag.get("Data") instanceof NumberTag dataTag) {
|
||||
data = dataTag.asByte();
|
||||
}
|
||||
|
||||
Integer flower = flowers.get(new Pair<>(item, (byte) data));
|
||||
if (flower != null) return flower;
|
||||
flower = flowers.get(new Pair<>(item, (byte) 0));
|
||||
if (flower != null) return flower;
|
||||
Integer flower = FLOWERS.get(new IntIdPair(item, data));
|
||||
if (flower != null) {
|
||||
return flower;
|
||||
}
|
||||
|
||||
return 5265; // Fallback to empty pot
|
||||
flower = FLOWERS.get(new IntIdPair(item, (byte) 0));
|
||||
if (flower != null) {
|
||||
return flower;
|
||||
}
|
||||
|
||||
return EMPTY_POT; // Fallback to empty pot
|
||||
}
|
||||
|
||||
private record IntIdPair(int id, byte data) {
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -205,23 +205,23 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
|
||||
String old = channel;
|
||||
channel = getOldPluginChannelId(channel);
|
||||
if (channel == null) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
if (Via.getManager().isDebug()) {
|
||||
protocol.getLogger().warning("Ignoring serverbound plugin message with channel: " + old);
|
||||
}
|
||||
wrapper.cancel();
|
||||
return;
|
||||
} else if (channel.equals("REGISTER") || channel.equals("UNREGISTER")) {
|
||||
String[] channels = new String(wrapper.read(Types.REMAINING_BYTES), StandardCharsets.UTF_8).split("\0");
|
||||
String[] channels = new String(wrapper.read(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA), StandardCharsets.UTF_8).split("\0");
|
||||
List<String> rewrittenChannels = new ArrayList<>();
|
||||
for (String s : channels) {
|
||||
String rewritten = getOldPluginChannelId(s);
|
||||
if (rewritten != null) {
|
||||
rewrittenChannels.add(rewritten);
|
||||
} else if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
} else if (Via.getManager().isDebug()) {
|
||||
protocol.getLogger().warning("Ignoring plugin channel in serverbound " + channel + ": " + s);
|
||||
}
|
||||
}
|
||||
wrapper.write(Types.REMAINING_BYTES, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
|
||||
wrapper.write(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA, Joiner.on('\0').join(rewrittenChannels).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
wrapper.set(Types.STRING, 0, channel);
|
||||
});
|
||||
|
||||
+4
-4
@@ -172,16 +172,16 @@ public class Protocol1_15_2To1_16 extends AbstractProtocol<ClientboundPackets1_1
|
||||
final String channel = wrapper.get(Types.STRING, 0);
|
||||
final String namespacedChannel = Key.namespaced(channel);
|
||||
if (channel.length() > 32) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
if (Via.getManager().isDebug()) {
|
||||
getLogger().warning("Ignoring serverbound plugin channel, as it is longer than 32 characters: " + channel);
|
||||
}
|
||||
wrapper.cancel();
|
||||
} else if (namespacedChannel.equals("minecraft:register") || namespacedChannel.equals("minecraft:unregister")) {
|
||||
String[] channels = new String(wrapper.read(Types.REMAINING_BYTES), StandardCharsets.UTF_8).split("\0");
|
||||
String[] channels = new String(wrapper.read(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA), StandardCharsets.UTF_8).split("\0");
|
||||
List<String> checkedChannels = new ArrayList<>(channels.length);
|
||||
for (String registeredChannel : channels) {
|
||||
if (registeredChannel.length() > 32) {
|
||||
if (!Via.getConfig().isSuppressConversionWarnings()) {
|
||||
if (Via.getManager().isDebug()) {
|
||||
getLogger().warning("Ignoring serverbound plugin channel register of '" + registeredChannel + "', as it is longer than 32 characters");
|
||||
}
|
||||
continue;
|
||||
@@ -195,7 +195,7 @@ public class Protocol1_15_2To1_16 extends AbstractProtocol<ClientboundPackets1_1
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.write(Types.REMAINING_BYTES, Joiner.on('\0').join(checkedChannels).getBytes(StandardCharsets.UTF_8));
|
||||
wrapper.write(Types.SERVERBOUND_CUSTOM_PAYLOAD_DATA, Joiner.on('\0').join(checkedChannels).getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+1
@@ -168,6 +168,7 @@ public final class WorldPacketRewriter1_18 {
|
||||
lightStorage.getLight(chunk.getX(), chunk.getZ()) : lightStorage.removeLight(chunk.getX(), chunk.getZ());
|
||||
if (light == null) {
|
||||
protocol.getLogger().warning("No light data found for chunk at " + chunk.getX() + ", " + chunk.getZ() + ". Chunk was already loaded: " + alreadyLoaded);
|
||||
protocol.getLogger().warning("This means another plugin is sending chunk data in a bad order, or you need to re-enable the cache-1_17-light config option.");
|
||||
|
||||
final BitSet emptyLightMask = new BitSet();
|
||||
emptyLightMask.set(0, tracker.currentWorldSectionHeight() + 2);
|
||||
|
||||
+3
-1
@@ -92,7 +92,9 @@ public final class Protocol1_17To1_17_1 extends AbstractProtocol<ClientboundPack
|
||||
ListTag<StringTag> pagesTag = new ListTag<>(StringTag.class);
|
||||
for (int i = 0; i < pages; i++) {
|
||||
String page = wrapper.read(PAGE_STRING_TYPE);
|
||||
pagesTag.add(new StringTag(page));
|
||||
if (i < 200) { // Apply network limit as per game code
|
||||
pagesTag.add(new StringTag(page));
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy servers don't like an empty pages list
|
||||
|
||||
+3
-5
@@ -50,7 +50,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
|
||||
wrapper.passthrough(Types.STRING); // Group
|
||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
||||
handleIngredients(wrapper);
|
||||
wrapper.write(mappedItemType(), rewrite(wrapper.user(), wrapper.read(itemType())));
|
||||
handleResult(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,8 +61,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
|
||||
for (int i = 0; i < ingredients; i++) {
|
||||
handleIngredient(wrapper);
|
||||
}
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,8 +69,7 @@ public class RecipeRewriter1_19_3<C extends ClientboundPacketType> extends Recip
|
||||
wrapper.passthrough(Types.STRING); // Group
|
||||
wrapper.passthrough(Types.VAR_INT); // Crafting book category
|
||||
handleIngredient(wrapper);
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
wrapper.passthrough(Types.FLOAT); // EXP
|
||||
wrapper.passthrough(Types.VAR_INT); // Cooking time
|
||||
}
|
||||
|
||||
+1
-1
@@ -77,6 +77,7 @@ public final class Protocol1_20_2To1_20_3 extends AbstractProtocol<ClientboundPa
|
||||
cancelServerbound(ServerboundPackets1_20_3.CONTAINER_SLOT_STATE_CHANGED);
|
||||
|
||||
tagRewriter.registerGeneric(ClientboundPackets1_20_2.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
|
||||
|
||||
final SoundRewriter<ClientboundPacket1_20_2> soundRewriter = new SoundRewriter<>(this);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_2.SOUND);
|
||||
@@ -307,7 +308,6 @@ public final class Protocol1_20_2To1_20_3 extends AbstractProtocol<ClientboundPa
|
||||
|
||||
registerServerbound(ServerboundConfigurationPackets1_20_2.RESOURCE_PACK, resourcePackStatusHandler());
|
||||
registerClientbound(ClientboundConfigurationPackets1_20_2.RESOURCE_PACK, ClientboundConfigurationPackets1_20_3.RESOURCE_PACK_PUSH, resourcePackHandler(ClientboundConfigurationPackets1_20_3.RESOURCE_PACK_POP));
|
||||
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
|
||||
}
|
||||
|
||||
private PacketHandler resourcePackStatusHandler() {
|
||||
|
||||
+1
-3
@@ -39,9 +39,7 @@ public class RecipeRewriter1_20_3<C extends ClientboundPacketType> extends Recip
|
||||
for (int i = 0; i < ingredients; i++) {
|
||||
handleIngredient(wrapper);
|
||||
}
|
||||
|
||||
final Item item = rewrite(wrapper.user(), wrapper.read(itemType())); // Result
|
||||
wrapper.write(mappedItemType(), item);
|
||||
handleResult(wrapper);
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show notification
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -270,13 +270,13 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
|
||||
.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_MODIFIERS1_20_5)
|
||||
.add(StructuredDataKey.CUSTOM_MODEL_DATA).add(StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP).add(StructuredDataKey.REPAIR_COST)
|
||||
.add(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5).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_20_5).add(StructuredDataKey.BUNDLE_CONTENTS1_20_5).add(StructuredDataKey.POTION_CONTENTS1_20_5)
|
||||
.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.TRIM1_20_5).add(StructuredDataKey.DEBUG_STICK_STATE).add(StructuredDataKey.ENTITY_DATA)
|
||||
.add(StructuredDataKey.BUCKET_ENTITY_DATA).add(StructuredDataKey.BLOCK_ENTITY_DATA).add(StructuredDataKey.INSTRUMENT1_20_5)
|
||||
.add(StructuredDataKey.RECIPES).add(StructuredDataKey.LODESTONE_TRACKER).add(StructuredDataKey.FIREWORK_EXPLOSION)
|
||||
.add(StructuredDataKey.FIREWORKS).add(StructuredDataKey.PROFILE).add(StructuredDataKey.NOTE_BLOCK_SOUND)
|
||||
|
||||
+31
-31
@@ -17,62 +17,62 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
|
||||
public final class MaxStackSize1_20_3 {
|
||||
|
||||
private static final Map<Integer, Integer> mapping = new HashMap<>();
|
||||
private static final Int2IntMap MAPPING = new Int2IntOpenHashMap();
|
||||
|
||||
static {
|
||||
fill(521, 537, 1);
|
||||
fill(764, 790, 1);
|
||||
mapping.put(793, 1);
|
||||
mapping.put(795, 1);
|
||||
mapping.put(797, 1);
|
||||
MAPPING.put(793, 1);
|
||||
MAPPING.put(795, 1);
|
||||
MAPPING.put(797, 1);
|
||||
fill(814, 843, 1);
|
||||
mapping.put(846, 1);
|
||||
mapping.put(853, 1);
|
||||
MAPPING.put(846, 1);
|
||||
MAPPING.put(853, 1);
|
||||
fill(854, 876, 1);
|
||||
fill(883, 905, 16);
|
||||
fill(906, 908, 1);
|
||||
mapping.put(909, 16);
|
||||
MAPPING.put(909, 16);
|
||||
fill(911, 917, 1);
|
||||
mapping.put(924, 16);
|
||||
mapping.put(927, 1);
|
||||
mapping.put(928, 1);
|
||||
mapping.put(930, 1);
|
||||
MAPPING.put(924, 16);
|
||||
MAPPING.put(927, 1);
|
||||
MAPPING.put(928, 1);
|
||||
MAPPING.put(930, 1);
|
||||
fill(960, 976, 1);
|
||||
mapping.put(980, 1);
|
||||
mapping.put(990, 16);
|
||||
mapping.put(995, 1);
|
||||
mapping.put(1085, 1);
|
||||
mapping.put(1086, 16);
|
||||
mapping.put(1107, 1);
|
||||
mapping.put(1113, 1);
|
||||
mapping.put(1116, 16);
|
||||
MAPPING.put(980, 1);
|
||||
MAPPING.put(990, 16);
|
||||
MAPPING.put(995, 1);
|
||||
MAPPING.put(1085, 1);
|
||||
MAPPING.put(1086, 16);
|
||||
MAPPING.put(1107, 1);
|
||||
MAPPING.put(1113, 1);
|
||||
MAPPING.put(1116, 16);
|
||||
fill(1117, 1120, 1);
|
||||
mapping.put(1123, 1);
|
||||
MAPPING.put(1123, 1);
|
||||
fill(1126, 1141, 16);
|
||||
mapping.put(1149, 1);
|
||||
mapping.put(1151, 1);
|
||||
MAPPING.put(1149, 1);
|
||||
MAPPING.put(1151, 1);
|
||||
fill(1154, 1156, 1);
|
||||
fill(1159, 1176, 1);
|
||||
mapping.put(1178, 1);
|
||||
mapping.put(1182, 1);
|
||||
mapping.put(1183, 1);
|
||||
MAPPING.put(1178, 1);
|
||||
MAPPING.put(1182, 1);
|
||||
MAPPING.put(1183, 1);
|
||||
fill(1185, 1191, 1);
|
||||
mapping.put(1212, 16);
|
||||
mapping.put(1256, 1);
|
||||
MAPPING.put(1212, 16);
|
||||
MAPPING.put(1256, 1);
|
||||
}
|
||||
|
||||
public static int getMaxStackSize(final int identifier) {
|
||||
return mapping.getOrDefault(identifier, 64);
|
||||
return MAPPING.getOrDefault(identifier, 64);
|
||||
}
|
||||
|
||||
private static void fill(final int start, final int end, final int value) {
|
||||
for (int i = start; i <= end; i++) {
|
||||
mapping.put(i, value);
|
||||
MAPPING.put(i, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -18,9 +18,10 @@
|
||||
package com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPacket1_21_2;
|
||||
|
||||
public enum ServerboundConfigurationPackets1_20_5 implements ServerboundPacket1_20_5, ServerboundPacket1_21_2 {
|
||||
public enum ServerboundConfigurationPackets1_20_5 implements ServerboundPacket1_20_5, ServerboundPacket1_21_2, ServerboundPacket1_21_4 {
|
||||
|
||||
CLIENT_INFORMATION, // 0x00
|
||||
COOKIE_RESPONSE, // 0x01
|
||||
|
||||
+8
-17
@@ -105,8 +105,7 @@ import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.SerializerVersion;
|
||||
import com.viaversion.viaversion.util.UUIDUtil;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -343,12 +342,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
}
|
||||
});
|
||||
|
||||
final RecipeRewriter1_20_3<ClientboundPacket1_20_3> recipeRewriter = new RecipeRewriter1_20_3<>(protocol) {
|
||||
@Override
|
||||
protected Item rewrite(final UserConnection connection, @Nullable Item item) {
|
||||
return handleNonEmptyItemToClient(connection, item);
|
||||
}
|
||||
};
|
||||
final RecipeRewriter1_20_5<ClientboundPacket1_20_3> recipeRewriter = new RecipeRewriter1_20_5<>(protocol);
|
||||
protocol.registerClientbound(ClientboundPackets1_20_3.UPDATE_RECIPES, wrapper -> {
|
||||
final int size = wrapper.passthrough(Types.VAR_INT);
|
||||
for (int i = 0; i < size; i++) {
|
||||
@@ -465,7 +459,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
|
||||
final NumberTag customModelData = tag.getNumberTag("CustomModelData");
|
||||
if (customModelData != null) {
|
||||
data.set(StructuredDataKey.CUSTOM_MODEL_DATA, customModelData.asInt());
|
||||
data.set(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, customModelData.asInt());
|
||||
}
|
||||
|
||||
final CompoundTag blockState = tag.getCompoundTag("BlockStateTag");
|
||||
@@ -625,7 +619,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
item.dataContainer().set(StructuredDataKey.MAX_DAMAGE, 326);
|
||||
}
|
||||
}
|
||||
if (serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_8)) {
|
||||
if (Via.getConfig().swordBlockingViaConsumable() && serverVersion.olderThanOrEqualTo(ProtocolVersion.v1_8)) {
|
||||
if (item.identifier() == 814 || item.identifier() == 819 || item.identifier() == 824 || item.identifier() == 829 || item.identifier() == 834) { // swords
|
||||
// Make sword "eatable" to enable clientside instant blocking on 1.8. Consume time is set really high, so the eating animation doesn't play
|
||||
item.dataContainer().set(StructuredDataKey.FOOD1_20_5, new FoodProperties1_20_5(0, 0F, true, 3600, null, new FoodEffect[0]));
|
||||
@@ -1000,17 +994,14 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
final CompoundTag overrideArmorMaterialsTag = materialCompoundTag.getCompoundTag("override_armor_materials");
|
||||
final Tag descriptionTag = materialCompoundTag.get("description");
|
||||
|
||||
final Int2ObjectMap<String> overrideArmorMaterials = new Int2ObjectOpenHashMap<>();
|
||||
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
|
||||
if (overrideArmorMaterialsTag != null) {
|
||||
for (final Map.Entry<String, Tag> entry : overrideArmorMaterialsTag.entrySet()) {
|
||||
if (!(entry.getValue() instanceof StringTag valueTag)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
final int id = Integer.parseInt(entry.getKey());
|
||||
overrideArmorMaterials.put(id, valueTag.getValue());
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
overrideArmorMaterials.put(entry.getKey(), valueTag.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1054,7 +1045,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
));
|
||||
} else return;
|
||||
|
||||
data.set(StructuredDataKey.TRIM, new ArmorTrim(materialHolder, patternHolder, showInTooltip));
|
||||
data.set(StructuredDataKey.TRIM1_20_5, new ArmorTrim(materialHolder, patternHolder, showInTooltip));
|
||||
}
|
||||
|
||||
private void updateMobTags(final StructuredDataContainer data, final CompoundTag tag) {
|
||||
|
||||
+4
-5
@@ -92,7 +92,6 @@ import com.viaversion.viaversion.util.SerializerVersion;
|
||||
import com.viaversion.viaversion.util.UUIDUtil;
|
||||
import com.viaversion.viaversion.util.Unit;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -126,7 +125,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
|
||||
register(StructuredDataKey.CAN_PLACE_ON, this::convertCanPlaceOn);
|
||||
register(StructuredDataKey.CAN_BREAK, this::convertCanBreak);
|
||||
register(StructuredDataKey.ATTRIBUTE_MODIFIERS1_20_5, this::convertAttributeModifiers);
|
||||
register(StructuredDataKey.CUSTOM_MODEL_DATA, this::convertCustomModelData);
|
||||
register(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, this::convertCustomModelData);
|
||||
register(StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP, this::convertHideAdditionalTooltip);
|
||||
register(StructuredDataKey.HIDE_TOOLTIP, this::convertHideTooltip);
|
||||
register(StructuredDataKey.REPAIR_COST, this::convertRepairCost);
|
||||
@@ -148,7 +147,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
|
||||
register(StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, this::convertSuspiciousStewEffects);
|
||||
register(StructuredDataKey.WRITABLE_BOOK_CONTENT, this::convertWritableBookContent);
|
||||
register(StructuredDataKey.WRITTEN_BOOK_CONTENT, this::convertWrittenBookContent);
|
||||
register(StructuredDataKey.TRIM, this::convertTrim);
|
||||
register(StructuredDataKey.TRIM1_20_5, this::convertTrim);
|
||||
register(StructuredDataKey.DEBUG_STICK_STATE, this::convertDebugStickRate);
|
||||
register(StructuredDataKey.ENTITY_DATA, this::convertEntityData);
|
||||
register(StructuredDataKey.BUCKET_ENTITY_DATA, this::convertBucketEntityData);
|
||||
@@ -693,8 +692,8 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Co
|
||||
}
|
||||
|
||||
final CompoundTag overrideArmorMaterialsTag = new CompoundTag();
|
||||
for (final Int2ObjectMap.Entry<String> entry : armorTrimMaterial.overrideArmorMaterials().int2ObjectEntrySet()) {
|
||||
final String materialKey = ArmorMaterials1_20_5.idToKey(entry.getIntKey());
|
||||
for (final Map.Entry<String, String> entry : armorTrimMaterial.overrideArmorMaterials().entrySet()) {
|
||||
final String materialKey = ArmorMaterials1_20_5.idToKey(Integer.parseInt(entry.getKey()));
|
||||
if (materialKey != null) {
|
||||
overrideArmorMaterialsTag.putString(materialKey, entry.getValue());
|
||||
}
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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_3to1_20_5.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.minecraft.item.StructuredItem;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.rewriter.RecipeRewriter1_20_3;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
final class RecipeRewriter1_20_5 <C extends ClientboundPacketType> extends RecipeRewriter1_20_3<C> {
|
||||
|
||||
public RecipeRewriter1_20_5(final Protocol<C, ?, ?, ?> protocol) {
|
||||
super(protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleIngredient(final PacketWrapper wrapper) {
|
||||
final Item[] items = wrapper.read(itemArrayType());
|
||||
final List<Item> newItems = new ArrayList<>(items.length);
|
||||
for (final Item item : items) {
|
||||
if (item == null || item.isEmpty()) continue;
|
||||
newItems.add(rewrite(wrapper.user(), item));
|
||||
}
|
||||
wrapper.write(mappedItemArrayType(), newItems.toArray(new Item[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleResult(final PacketWrapper wrapper) {
|
||||
Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
if (result == null || result.isEmpty()) {
|
||||
result = new StructuredItem(1, 1);
|
||||
}
|
||||
wrapper.write(mappedItemType(), result);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -65,7 +65,6 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.storage.BannerPattern
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import com.viaversion.viaversion.util.UUIDUtil;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -136,6 +135,7 @@ public final class StructuredDataConverter {
|
||||
}
|
||||
|
||||
final CompoundTag modifierTag = new CompoundTag();
|
||||
modifierTag.put("UUID", new IntArrayTag(UUIDUtil.toIntArray(modifier.modifier().uuid())));
|
||||
modifierTag.putString("AttributeName", identifier.equals("generic.jump_strength") ? "horse.jump_strength" : identifier);
|
||||
modifierTag.putString("Name", modifier.modifier().name());
|
||||
modifierTag.putDouble("Amount", modifier.modifier().amount());
|
||||
@@ -151,7 +151,7 @@ public final class StructuredDataConverter {
|
||||
putHideFlag(tag, HIDE_ATTRIBUTES);
|
||||
}
|
||||
});
|
||||
register(StructuredDataKey.CUSTOM_MODEL_DATA, (data, tag) -> tag.putInt("CustomModelData", data));
|
||||
register(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, (data, tag) -> tag.putInt("CustomModelData", data));
|
||||
register(StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP, (data, tag) -> putHideFlag(tag, 0x20));
|
||||
register(StructuredDataKey.REPAIR_COST, (data, tag) -> tag.putInt("RepairCost", data));
|
||||
register(StructuredDataKey.DYED_COLOR, (data, tag) -> {
|
||||
@@ -513,7 +513,7 @@ public final class StructuredDataConverter {
|
||||
tag.putInt("map_scale_direction", 1);
|
||||
}
|
||||
});
|
||||
register(StructuredDataKey.TRIM, (connection, data, tag) -> {
|
||||
register(StructuredDataKey.TRIM1_20_5, (connection, data, tag) -> {
|
||||
final CompoundTag trimTag = new CompoundTag();
|
||||
final ArmorTrimStorage trimStorage = connection.get(ArmorTrimStorage.class);
|
||||
if (data.material().isDirect()) {
|
||||
@@ -530,8 +530,8 @@ public final class StructuredDataConverter {
|
||||
|
||||
final CompoundTag overrideArmorMaterials = new CompoundTag();
|
||||
if (!material.overrideArmorMaterials().isEmpty()) {
|
||||
for (final Int2ObjectMap.Entry<String> entry : material.overrideArmorMaterials().int2ObjectEntrySet()) {
|
||||
overrideArmorMaterials.put(Integer.toString(entry.getIntKey()), new StringTag(entry.getValue()));
|
||||
for (final Map.Entry<String, String> entry : material.overrideArmorMaterials().entrySet()) {
|
||||
overrideArmorMaterials.put(entry.getKey(), new StringTag(entry.getValue()));
|
||||
}
|
||||
materialTag.put("override_armor_materials", overrideArmorMaterials);
|
||||
}
|
||||
|
||||
+4
-4
@@ -46,7 +46,7 @@ import com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter.BlockItemPacke
|
||||
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.protocols.v1_20_5to1_21.storage.OnGroundTracker;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.PlayerPositionStorage;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ParticleRewriter;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
@@ -203,13 +203,13 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
|
||||
.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.CUSTOM_MODEL_DATA1_20_5).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_CONTENTS1_20_5)
|
||||
.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.TRIM1_20_5).add(StructuredDataKey.DEBUG_STICK_STATE).add(StructuredDataKey.ENTITY_DATA)
|
||||
.add(StructuredDataKey.BUCKET_ENTITY_DATA).add(StructuredDataKey.BLOCK_ENTITY_DATA).add(StructuredDataKey.INSTRUMENT1_20_5)
|
||||
.add(StructuredDataKey.RECIPES).add(StructuredDataKey.LODESTONE_TRACKER).add(StructuredDataKey.FIREWORK_EXPLOSION)
|
||||
.add(StructuredDataKey.FIREWORKS).add(StructuredDataKey.PROFILE).add(StructuredDataKey.NOTE_BLOCK_SOUND)
|
||||
@@ -234,7 +234,7 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
|
||||
public void init(final UserConnection connection) {
|
||||
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_20_5.PLAYER));
|
||||
connection.put(new EfficiencyAttributeStorage());
|
||||
connection.put(new OnGroundTracker());
|
||||
connection.put(new PlayerPositionStorage());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+40
-5
@@ -26,6 +26,7 @@ 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.minecraft.item.data.Enchantments;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
|
||||
@@ -38,7 +39,8 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPac
|
||||
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.protocols.v1_20_5to1_21.storage.OnGroundTracker;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.PlayerPositionStorage;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
import java.util.Arrays;
|
||||
@@ -48,6 +50,14 @@ import java.util.Objects;
|
||||
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");
|
||||
private static final int HELMET_SLOT = 5;
|
||||
private static final int CHESTPLATE_SLOT = 6;
|
||||
private static final int LEGGINGS_SLOT = 7;
|
||||
private static final int BOOTS_SLOT = 8;
|
||||
|
||||
private static final int AQUA_AFFINITY_ID = 6;
|
||||
private static final int DEPTH_STRIDER_ID = 8;
|
||||
private static final int SWIFT_SNEAK_ID = 12;
|
||||
|
||||
public BlockItemPacketRewriter1_21(final Protocol1_20_5To1_21 protocol) {
|
||||
super(protocol,
|
||||
@@ -67,7 +77,29 @@ public final class BlockItemPacketRewriter1_21 extends StructuredItemRewriter<Cl
|
||||
|
||||
registerCooldown(ClientboundPackets1_20_5.COOLDOWN);
|
||||
registerSetContent1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_CONTENT);
|
||||
registerSetSlot1_17_1(ClientboundPackets1_20_5.CONTAINER_SET_SLOT);
|
||||
protocol.registerClientbound(ClientboundPackets1_20_5.CONTAINER_SET_SLOT, wrapper -> {
|
||||
final short containerId = wrapper.passthrough(Types.UNSIGNED_BYTE); // Container id
|
||||
wrapper.passthrough(Types.VAR_INT); // State id
|
||||
final short slotId = wrapper.passthrough(Types.SHORT); // Slot id
|
||||
final Item item = handleItemToClient(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), item);
|
||||
|
||||
// When a players' armor is set, update their attributes
|
||||
if (containerId != 0 || slotId > BOOTS_SLOT || slotId < HELMET_SLOT || slotId == CHESTPLATE_SLOT) {
|
||||
return;
|
||||
}
|
||||
|
||||
final EfficiencyAttributeStorage storage = wrapper.user().get(EfficiencyAttributeStorage.class);
|
||||
Enchantments enchants = item.dataContainer().get(StructuredDataKey.ENCHANTMENTS);
|
||||
EfficiencyAttributeStorage.ActiveEnchants active = storage.activeEnchants();
|
||||
active = switch (slotId) {
|
||||
case HELMET_SLOT -> active.aquaAffinity(enchants == null ? 0 : enchants.getLevel(AQUA_AFFINITY_ID));
|
||||
case LEGGINGS_SLOT -> active.swiftSneak(enchants == null ? 0 : enchants.getLevel(SWIFT_SNEAK_ID));
|
||||
case BOOTS_SLOT -> active.depthStrider(enchants == null ? 0 : enchants.getLevel(DEPTH_STRIDER_ID));
|
||||
default -> active;
|
||||
};
|
||||
storage.setEnchants(-1, wrapper.user(), active);
|
||||
});
|
||||
registerAdvancements1_20_3(ClientboundPackets1_20_5.UPDATE_ADVANCEMENTS);
|
||||
registerSetEquipment(ClientboundPackets1_20_5.SET_EQUIPMENT);
|
||||
registerContainerClick1_17_1(ServerboundPackets1_20_5.CONTAINER_CLICK);
|
||||
@@ -111,13 +143,16 @@ public final class BlockItemPacketRewriter1_21 extends StructuredItemRewriter<Cl
|
||||
if (!Via.getConfig().fix1_21PlacementRotation()) {
|
||||
return;
|
||||
}
|
||||
final OnGroundTracker tracker = wrapper.user().get(OnGroundTracker.class);
|
||||
final PlayerPositionStorage storage = wrapper.user().get(PlayerPositionStorage.class);
|
||||
|
||||
// Not correct but *enough* for vanilla/normal servers to have block placement synchronized
|
||||
final PacketWrapper playerRotation = wrapper.create(ServerboundPackets1_20_5.MOVE_PLAYER_ROT);
|
||||
final PacketWrapper playerRotation = wrapper.create(ServerboundPackets1_20_5.MOVE_PLAYER_POS_ROT);
|
||||
playerRotation.write(Types.DOUBLE, storage.x());
|
||||
playerRotation.write(Types.DOUBLE, storage.y());
|
||||
playerRotation.write(Types.DOUBLE, storage.z());
|
||||
playerRotation.write(Types.FLOAT, yaw);
|
||||
playerRotation.write(Types.FLOAT, pitch);
|
||||
playerRotation.write(Types.BOOLEAN, tracker.onGround());
|
||||
playerRotation.write(Types.BOOLEAN, storage.onGround());
|
||||
|
||||
playerRotation.sendToServer(Protocol1_20_5To1_21.class);
|
||||
wrapper.sendToServer(Protocol1_20_5To1_21.class);
|
||||
|
||||
+36
-23
@@ -38,7 +38,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPac
|
||||
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.protocols.v1_20_5to1_21.storage.OnGroundTracker;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.PlayerPositionStorage;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
|
||||
|
||||
@@ -111,7 +111,8 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
|
||||
map(Types.STRING); // World
|
||||
handler(worldDataTrackerHandlerByKey1_20_5(3));
|
||||
handler(playerTrackerHandler());
|
||||
handler(wrapper -> wrapper.user().get(EfficiencyAttributeStorage.class).onLoginSent(wrapper.user()));
|
||||
handler(wrapper -> wrapper.user().get(EfficiencyAttributeStorage.class)
|
||||
.onLoginSent(wrapper.get(Types.INT, 0), wrapper.user()));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -122,39 +123,51 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
|
||||
|
||||
// Resend attribute modifiers from items
|
||||
wrapper.user().get(EfficiencyAttributeStorage.class).onRespawn(wrapper.user());
|
||||
|
||||
wrapper.user().put(new PlayerPositionStorage());
|
||||
});
|
||||
|
||||
// Tracks on ground state for block interactions
|
||||
if (!Via.getConfig().fix1_21PlacementRotation()) {
|
||||
return;
|
||||
}
|
||||
// Tracking player position and on ground for block interactions, rotations is kept from the interaction packet
|
||||
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_POS, wrapper -> {
|
||||
wrapper.passthrough(Types.DOUBLE); // X
|
||||
wrapper.passthrough(Types.DOUBLE); // Y
|
||||
wrapper.passthrough(Types.DOUBLE); // Z
|
||||
|
||||
wrapper.user().get(OnGroundTracker.class).setOnGround(wrapper.passthrough(Types.BOOLEAN));
|
||||
if (Via.getConfig().fix1_21PlacementRotation()) {
|
||||
storePosition(wrapper);
|
||||
storeOnGround(wrapper);
|
||||
}
|
||||
});
|
||||
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_ROT, wrapper -> {
|
||||
wrapper.passthrough(Types.FLOAT); // Yaw
|
||||
wrapper.passthrough(Types.FLOAT); // Pitch
|
||||
|
||||
wrapper.user().get(OnGroundTracker.class).setOnGround(wrapper.passthrough(Types.BOOLEAN));
|
||||
if (Via.getConfig().fix1_21PlacementRotation()) {
|
||||
wrapper.passthrough(Types.FLOAT); // Yaw
|
||||
wrapper.passthrough(Types.FLOAT); // Pitch
|
||||
storeOnGround(wrapper);
|
||||
}
|
||||
});
|
||||
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_POS_ROT, wrapper -> {
|
||||
wrapper.passthrough(Types.DOUBLE); // X
|
||||
wrapper.passthrough(Types.DOUBLE); // Y
|
||||
wrapper.passthrough(Types.DOUBLE); // Z
|
||||
wrapper.passthrough(Types.FLOAT); // Yaw
|
||||
wrapper.passthrough(Types.FLOAT); // Pitch
|
||||
|
||||
wrapper.user().get(OnGroundTracker.class).setOnGround(wrapper.passthrough(Types.BOOLEAN));
|
||||
if (Via.getConfig().fix1_21PlacementRotation()) {
|
||||
storePosition(wrapper);
|
||||
wrapper.passthrough(Types.FLOAT); // Yaw
|
||||
wrapper.passthrough(Types.FLOAT); // Pitch
|
||||
storeOnGround(wrapper);
|
||||
}
|
||||
});
|
||||
protocol.registerServerbound(ServerboundPackets1_20_5.MOVE_PLAYER_STATUS_ONLY, wrapper -> {
|
||||
wrapper.user().get(OnGroundTracker.class).setOnGround(wrapper.passthrough(Types.BOOLEAN));
|
||||
if (Via.getConfig().fix1_21PlacementRotation()) {
|
||||
storeOnGround(wrapper);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void storePosition(final PacketWrapper wrapper) {
|
||||
final double x = wrapper.passthrough(Types.DOUBLE);
|
||||
final double y = wrapper.passthrough(Types.DOUBLE);
|
||||
final double z = wrapper.passthrough(Types.DOUBLE);
|
||||
wrapper.user().get(PlayerPositionStorage.class).setPosition(x, y, z);
|
||||
}
|
||||
|
||||
private void storeOnGround(final PacketWrapper wrapper) {
|
||||
final boolean onGround = wrapper.passthrough(Types.BOOLEAN);
|
||||
wrapper.user().get(PlayerPositionStorage.class).setOnGround(onGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
filter().handler((event, data) -> {
|
||||
|
||||
+60
-19
@@ -45,25 +45,10 @@ public final class EfficiencyAttributeStorage implements StorableObject {
|
||||
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;
|
||||
}
|
||||
|
||||
public void setEnchants(final int entityId, final UserConnection connection, final ActiveEnchants enchants) {
|
||||
if (activeEnchants == enchants) return;
|
||||
synchronized (lock) {
|
||||
this.activeEnchants = new ActiveEnchants(entityId,
|
||||
new ActiveEnchant(activeEnchants.efficiency, efficiency),
|
||||
new ActiveEnchant(activeEnchants.soulSpeed, soulSpeed),
|
||||
new ActiveEnchant(activeEnchants.swiftSneak, swiftSneak),
|
||||
new ActiveEnchant(activeEnchants.aquaAffinity, aquaAffinity),
|
||||
new ActiveEnchant(activeEnchants.depthStrider, depthStrider)
|
||||
);
|
||||
this.activeEnchants = entityId == -1 ? enchants : enchants.withEntityId(entityId);
|
||||
this.attributesSent = false;
|
||||
}
|
||||
sendAttributesPacket(connection, false);
|
||||
@@ -73,7 +58,10 @@ public final class EfficiencyAttributeStorage implements StorableObject {
|
||||
return activeEnchants;
|
||||
}
|
||||
|
||||
public void onLoginSent(final UserConnection connection) {
|
||||
public void onLoginSent(final int entityId, final UserConnection connection) {
|
||||
synchronized (lock) {
|
||||
activeEnchants = activeEnchants.withEntityId(entityId);
|
||||
}
|
||||
// Always called from the netty thread
|
||||
this.loginSent = true;
|
||||
sendAttributesPacket(connection, false);
|
||||
@@ -128,6 +116,59 @@ public final class EfficiencyAttributeStorage implements StorableObject {
|
||||
|
||||
public record ActiveEnchants(int entityId, ActiveEnchant efficiency, ActiveEnchant soulSpeed,
|
||||
ActiveEnchant swiftSneak, ActiveEnchant aquaAffinity, ActiveEnchant depthStrider) {
|
||||
private ActiveEnchants withEntityId(int entityId) {
|
||||
return this.entityId == entityId ? this : new ActiveEnchants(entityId,
|
||||
efficiency,
|
||||
soulSpeed,
|
||||
swiftSneak,
|
||||
aquaAffinity,
|
||||
depthStrider);
|
||||
}
|
||||
|
||||
public ActiveEnchants efficiency(int level) {
|
||||
return efficiency.level == level ? this : new ActiveEnchants(entityId,
|
||||
new ActiveEnchant(efficiency, level),
|
||||
soulSpeed,
|
||||
swiftSneak,
|
||||
aquaAffinity,
|
||||
depthStrider);
|
||||
}
|
||||
|
||||
public ActiveEnchants soulSpeed(int level) {
|
||||
return soulSpeed.level == level ? this : new ActiveEnchants(entityId,
|
||||
efficiency,
|
||||
new ActiveEnchant(soulSpeed, level),
|
||||
swiftSneak,
|
||||
aquaAffinity,
|
||||
depthStrider);
|
||||
}
|
||||
|
||||
public ActiveEnchants swiftSneak(int level) {
|
||||
return swiftSneak.level == level ? this : new ActiveEnchants(entityId,
|
||||
efficiency,
|
||||
soulSpeed,
|
||||
new ActiveEnchant(swiftSneak, level),
|
||||
aquaAffinity,
|
||||
depthStrider);
|
||||
}
|
||||
|
||||
public ActiveEnchants aquaAffinity(int level) {
|
||||
return aquaAffinity.level == level ? this : new ActiveEnchants(entityId,
|
||||
efficiency,
|
||||
soulSpeed,
|
||||
swiftSneak,
|
||||
new ActiveEnchant(aquaAffinity, level),
|
||||
depthStrider);
|
||||
}
|
||||
|
||||
public ActiveEnchants depthStrider(int level) {
|
||||
return depthStrider.level == level ? this : new ActiveEnchants(entityId,
|
||||
efficiency,
|
||||
soulSpeed,
|
||||
swiftSneak,
|
||||
aquaAffinity,
|
||||
new ActiveEnchant(depthStrider, level));
|
||||
}
|
||||
}
|
||||
|
||||
public record ActiveEnchant(EnchantAttributeModifier modifier, int previousLevel, int level) {
|
||||
|
||||
+22
-1
@@ -19,10 +19,31 @@ package com.viaversion.viaversion.protocols.v1_20_5to1_21.storage;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
|
||||
public final class OnGroundTracker implements StorableObject {
|
||||
public final class PlayerPositionStorage implements StorableObject {
|
||||
|
||||
private double x;
|
||||
private double y;
|
||||
private double z;
|
||||
private boolean onGround;
|
||||
|
||||
public double x() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double y() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double z() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public void setPosition(final double x, final double y, final double z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public boolean onGround() {
|
||||
return onGround;
|
||||
}
|
||||
+17
-7
@@ -124,11 +124,7 @@ public final class Protocol1_20To1_20_2 extends AbstractProtocol<ClientboundPack
|
||||
wrapper.resetReader();
|
||||
wrapper.user().put(new LastTags(wrapper));
|
||||
});
|
||||
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, wrapper -> {
|
||||
tagRewriter.handleGeneric(wrapper);
|
||||
wrapper.resetReader();
|
||||
wrapper.user().put(new LastTags(wrapper));
|
||||
});
|
||||
registerClientbound(State.CONFIGURATION, ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, this::handleConfigTags);
|
||||
|
||||
registerClientbound(ClientboundPackets1_19_4.SET_DISPLAY_OBJECTIVE, wrapper -> {
|
||||
final byte slot = wrapper.read(Types.BYTE);
|
||||
@@ -229,6 +225,15 @@ public final class Protocol1_20To1_20_2 extends AbstractProtocol<ClientboundPack
|
||||
});
|
||||
}
|
||||
|
||||
private void handleConfigTags(final PacketWrapper wrapper) {
|
||||
tagRewriter.handleGeneric(wrapper);
|
||||
wrapper.resetReader();
|
||||
|
||||
final LastTags lastTags = new LastTags(wrapper);
|
||||
lastTags.setSentDuringConfigPhase(true);
|
||||
wrapper.user().put(lastTags);
|
||||
}
|
||||
|
||||
private static void sanitizeCustomPayload(final PacketWrapper wrapper) {
|
||||
final String channel = Key.namespaced(wrapper.get(Types.STRING, 0));
|
||||
if (channel.equals("minecraft:brand")) {
|
||||
@@ -299,6 +304,7 @@ public final class Protocol1_20To1_20_2 extends AbstractProtocol<ClientboundPack
|
||||
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_ENABLED_FEATURES.getId()) {
|
||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_ENABLED_FEATURES);
|
||||
} else if (unmappedId == ClientboundPackets1_19_4.UPDATE_TAGS.getId()) {
|
||||
handleConfigTags(packetWrapper); // Manually put through handler
|
||||
packetWrapper.setPacketType(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS);
|
||||
} else {
|
||||
// Not a packet that can be mapped to the configuration protocol
|
||||
@@ -327,8 +333,12 @@ public final class Protocol1_20To1_20_2 extends AbstractProtocol<ClientboundPack
|
||||
|
||||
final LastTags lastTags = connection.get(LastTags.class);
|
||||
if (lastTags != null) {
|
||||
// The server might still follow up with a tags packet, but we wouldn't know
|
||||
lastTags.sendLastTags(connection);
|
||||
if (lastTags.sentDuringConfigPhase()) {
|
||||
lastTags.setSentDuringConfigPhase(false);
|
||||
} else {
|
||||
// The server might still follow up with a tags packet, but we wouldn't know
|
||||
lastTags.sendLastTags(connection);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastResourcePack != null && connection.getProtocolInfo().protocolVersion() == ProtocolVersion.v1_20_2) {
|
||||
|
||||
+9
@@ -31,6 +31,7 @@ import java.util.List;
|
||||
public class LastTags implements StorableObject {
|
||||
|
||||
private final List<RegistryTags> registryTags = new ArrayList<>();
|
||||
private boolean sentDuringConfigPhase;
|
||||
|
||||
public LastTags(final PacketWrapper wrapper) {
|
||||
final int length = wrapper.passthrough(Types.VAR_INT);
|
||||
@@ -65,6 +66,14 @@ public class LastTags implements StorableObject {
|
||||
packet.send(Protocol1_20To1_20_2.class);
|
||||
}
|
||||
|
||||
public void setSentDuringConfigPhase(final boolean sentDuringConfigPhase) {
|
||||
this.sentDuringConfigPhase = sentDuringConfigPhase;
|
||||
}
|
||||
|
||||
public boolean sentDuringConfigPhase() {
|
||||
return sentDuringConfigPhase;
|
||||
}
|
||||
|
||||
private record RegistryTags(String registryKey, List<TagData> tags) {
|
||||
}
|
||||
}
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* 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_21_2to1_21_4;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.data.MappingDataBase;
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
|
||||
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
|
||||
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_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.provider.PickItemProvider;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.rewriter.BlockItemPacketRewriter1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.rewriter.ComponentRewriter1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.rewriter.EntityPacketRewriter1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.rewriter.ParticleRewriter1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.AttributeRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ParticleRewriter;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
|
||||
import com.viaversion.viaversion.rewriter.TagRewriter;
|
||||
import java.util.BitSet;
|
||||
|
||||
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
|
||||
|
||||
public final class Protocol1_21_2To1_21_4 extends AbstractProtocol<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_2, ServerboundPacket1_21_4> {
|
||||
|
||||
public static final MappingData MAPPINGS = new MappingDataBase("1.21.2", "1.21.4");
|
||||
private final EntityPacketRewriter1_21_4 entityRewriter = new EntityPacketRewriter1_21_4(this);
|
||||
private final BlockItemPacketRewriter1_21_4 itemRewriter = new BlockItemPacketRewriter1_21_4(this);
|
||||
private final ParticleRewriter<ClientboundPacket1_21_2> particleRewriter = new ParticleRewriter1_21_4(this);
|
||||
private final TagRewriter<ClientboundPacket1_21_2> tagRewriter = new TagRewriter<>(this);
|
||||
private final ComponentRewriter<ClientboundPacket1_21_2> componentRewriter = new ComponentRewriter1_21_4(this);
|
||||
|
||||
public Protocol1_21_2To1_21_4() {
|
||||
super(ClientboundPacket1_21_2.class, ClientboundPacket1_21_2.class, ServerboundPacket1_21_2.class, ServerboundPacket1_21_4.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
super.registerPackets();
|
||||
|
||||
tagRewriter.registerGeneric(ClientboundPackets1_21_2.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
|
||||
|
||||
componentRewriter.registerOpenScreen(ClientboundPackets1_21_2.OPEN_SCREEN);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_ACTION_BAR_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_TITLE_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SET_SUBTITLE_TEXT);
|
||||
componentRewriter.registerBossEvent(ClientboundPackets1_21_2.BOSS_EVENT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISCONNECT);
|
||||
componentRewriter.registerTabList(ClientboundPackets1_21_2.TAB_LIST);
|
||||
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21_2.PLAYER_COMBAT_KILL);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.SYSTEM_CHAT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21_2.DISGUISED_CHAT);
|
||||
componentRewriter.registerPing();
|
||||
|
||||
particleRewriter.registerExplode1_21_2(ClientboundPackets1_21_2.EXPLODE);
|
||||
registerClientbound(ClientboundPackets1_21_2.LEVEL_PARTICLES, wrapper -> {
|
||||
wrapper.passthrough(Types.BOOLEAN); // Override limiter
|
||||
wrapper.write(Types.BOOLEAN, false); // Always show
|
||||
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
|
||||
wrapper.passthrough(Types.FLOAT); // Particle Data
|
||||
wrapper.passthrough(Types.INT); // Particle Count
|
||||
|
||||
final Particle particle = wrapper.passthroughAndMap(Types1_21_2.PARTICLE, Types1_21_4.PARTICLE);
|
||||
particleRewriter.rewriteParticle(wrapper.user(), particle);
|
||||
});
|
||||
|
||||
final SoundRewriter<ClientboundPacket1_21_2> soundRewriter = new SoundRewriter<>(this);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_2.SOUND_ENTITY);
|
||||
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets1_21_2.AWARD_STATS);
|
||||
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_2.UPDATE_ATTRIBUTES);
|
||||
|
||||
registerClientbound(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE, wrapper -> {
|
||||
// Added "show hat" - true by default, keep it like that
|
||||
final BitSet actions = wrapper.passthroughAndMap(Types.PROFILE_ACTIONS_ENUM1_21_2, Types.PROFILE_ACTIONS_ENUM1_21_4);
|
||||
if (!actions.get(5)) { // Update display name
|
||||
return;
|
||||
}
|
||||
|
||||
final int entries = wrapper.passthrough(Types.VAR_INT);
|
||||
for (int i = 0; i < entries; i++) {
|
||||
wrapper.passthrough(Types.UUID);
|
||||
if (actions.get(0)) {
|
||||
wrapper.passthrough(Types.STRING); // Player Name
|
||||
|
||||
final int properties = wrapper.passthrough(Types.VAR_INT);
|
||||
for (int j = 0; j < properties; j++) {
|
||||
wrapper.passthrough(Types.STRING); // Name
|
||||
wrapper.passthrough(Types.STRING); // Value
|
||||
wrapper.passthrough(Types.OPTIONAL_STRING); // Signature
|
||||
}
|
||||
}
|
||||
if (actions.get(1) && wrapper.passthrough(Types.BOOLEAN)) {
|
||||
wrapper.passthrough(Types.UUID); // Session UUID
|
||||
wrapper.passthrough(Types.PROFILE_KEY);
|
||||
}
|
||||
if (actions.get(2)) {
|
||||
wrapper.passthrough(Types.VAR_INT); // Gamemode
|
||||
}
|
||||
if (actions.get(3)) {
|
||||
wrapper.passthrough(Types.BOOLEAN); // Listed
|
||||
}
|
||||
if (actions.get(4)) {
|
||||
wrapper.passthrough(Types.VAR_INT); // Latency
|
||||
}
|
||||
componentRewriter.processTag(wrapper.user(), wrapper.passthrough(Types.OPTIONAL_TAG));
|
||||
if (actions.get(6)) {
|
||||
wrapper.passthrough(Types.VAR_INT); // List order
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMappingDataLoaded() {
|
||||
EntityTypes1_21_4.initialize(this);
|
||||
Types1_21_4.PARTICLE.filler(this)
|
||||
.reader("block", ParticleType.Readers.BLOCK)
|
||||
.reader("block_marker", ParticleType.Readers.BLOCK)
|
||||
.reader("dust_pillar", ParticleType.Readers.BLOCK)
|
||||
.reader("falling_dust", ParticleType.Readers.BLOCK)
|
||||
.reader("block_crumble", ParticleType.Readers.BLOCK)
|
||||
.reader("dust", ParticleType.Readers.DUST1_21_2)
|
||||
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION1_21_2)
|
||||
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
|
||||
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
|
||||
.reader("shriek", ParticleType.Readers.SHRIEK)
|
||||
.reader("entity_effect", ParticleType.Readers.COLOR)
|
||||
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
|
||||
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));
|
||||
Types1_21_4.STRUCTURED_DATA.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
|
||||
StructuredDataKey.UNBREAKABLE, StructuredDataKey.RARITY, StructuredDataKey.HIDE_TOOLTIP, StructuredDataKey.DAMAGE_RESISTANT,
|
||||
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS, StructuredDataKey.CAN_PLACE_ON,
|
||||
StructuredDataKey.CAN_BREAK, StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP,
|
||||
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
|
||||
StructuredDataKey.INTANGIBLE_PROJECTILE, StructuredDataKey.STORED_ENCHANTMENTS, StructuredDataKey.DYED_COLOR,
|
||||
StructuredDataKey.MAP_COLOR, StructuredDataKey.MAP_ID, StructuredDataKey.MAP_DECORATIONS, StructuredDataKey.MAP_POST_PROCESSING,
|
||||
StructuredDataKey.POTION_CONTENTS1_21_2, StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, StructuredDataKey.WRITABLE_BOOK_CONTENT,
|
||||
StructuredDataKey.WRITTEN_BOOK_CONTENT, StructuredDataKey.TRIM1_21_4, StructuredDataKey.DEBUG_STICK_STATE, StructuredDataKey.ENTITY_DATA,
|
||||
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA, StructuredDataKey.INSTRUMENT1_21_2,
|
||||
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
|
||||
StructuredDataKey.PROFILE, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
|
||||
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES, StructuredDataKey.LOCK,
|
||||
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
|
||||
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21,
|
||||
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
|
||||
StructuredDataKey.USE_COOLDOWN, StructuredDataKey.DAMAGE, StructuredDataKey.EQUIPPABLE, StructuredDataKey.ITEM_MODEL,
|
||||
StructuredDataKey.GLIDER, StructuredDataKey.TOOLTIP_STYLE, StructuredDataKey.DEATH_PROTECTION,
|
||||
// Volatile thanks to containing item
|
||||
StructuredDataKey.CHARGED_PROJECTILES1_21_4, StructuredDataKey.BUNDLE_CONTENTS1_21_4, StructuredDataKey.CONTAINER1_21_4, StructuredDataKey.USE_REMAINDER1_21_4);
|
||||
super.onMappingDataLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(final ViaProviders providers) {
|
||||
providers.register(PickItemProvider.class, new PickItemProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final UserConnection connection) {
|
||||
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_4.PLAYER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingData getMappingData() {
|
||||
return MAPPINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityPacketRewriter1_21_4 getEntityRewriter() {
|
||||
return entityRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockItemPacketRewriter1_21_4 getItemRewriter() {
|
||||
return itemRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParticleRewriter<ClientboundPacket1_21_2> getParticleRewriter() {
|
||||
return particleRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagRewriter<ClientboundPacket1_21_2> getTagRewriter() {
|
||||
return tagRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentRewriter<ClientboundPacket1_21_2> getComponentRewriter() {
|
||||
return componentRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PacketTypesProvider<ClientboundPacket1_21_2, ClientboundPacket1_21_2, ServerboundPacket1_21_2, ServerboundPacket1_21_4> createPacketTypesProvider() {
|
||||
return new SimplePacketTypesProvider<>(
|
||||
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21_2.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_21_2.class, ServerboundConfigurationPackets1_20_5.class),
|
||||
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_21_4.class, ServerboundConfigurationPackets1_20_5.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
+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_21_2to1_21_4.packet;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
|
||||
public interface ServerboundPacket1_21_4 extends ServerboundPacketType {
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet;
|
||||
|
||||
public enum ServerboundPackets1_21_4 implements ServerboundPacket1_21_4 {
|
||||
|
||||
ACCEPT_TELEPORTATION, // 0x00
|
||||
BLOCK_ENTITY_TAG_QUERY, // 0x01
|
||||
BUNDLE_ITEM_SELECTED, // 0x02
|
||||
CHANGE_DIFFICULTY, // 0x03
|
||||
CHAT_ACK, // 0x04
|
||||
CHAT_COMMAND, // 0x05
|
||||
CHAT_COMMAND_SIGNED, // 0x06
|
||||
CHAT, // 0x07
|
||||
CHAT_SESSION_UPDATE, // 0x08
|
||||
CHUNK_BATCH_RECEIVED, // 0x09
|
||||
CLIENT_COMMAND, // 0x0A
|
||||
CLIENT_TICK_END, // 0x0B
|
||||
CLIENT_INFORMATION, // 0x0C
|
||||
COMMAND_SUGGESTION, // 0x0D
|
||||
CONFIGURATION_ACKNOWLEDGED, // 0x0E
|
||||
CONTAINER_BUTTON_CLICK, // 0x0F
|
||||
CONTAINER_CLICK, // 0x10
|
||||
CONTAINER_CLOSE, // 0x11
|
||||
CONTAINER_SLOT_STATE_CHANGED, // 0x12
|
||||
COOKIE_RESPONSE, // 0x13
|
||||
CUSTOM_PAYLOAD, // 0x14
|
||||
DEBUG_SAMPLE_SUBSCRIPTION, // 0x15
|
||||
EDIT_BOOK, // 0x16
|
||||
ENTITY_TAG_QUERY, // 0x17
|
||||
INTERACT, // 0x18
|
||||
JIGSAW_GENERATE, // 0x19
|
||||
KEEP_ALIVE, // 0x1A
|
||||
LOCK_DIFFICULTY, // 0x1B
|
||||
MOVE_PLAYER_POS, // 0x1C
|
||||
MOVE_PLAYER_POS_ROT, // 0x1D
|
||||
MOVE_PLAYER_ROT, // 0x1E
|
||||
MOVE_PLAYER_STATUS_ONLY, // 0x1F
|
||||
MOVE_VEHICLE, // 0x20
|
||||
PADDLE_BOAT, // 0x21
|
||||
PICK_ITEM_FROM_BLOCK, // 0x22
|
||||
PICK_ITEM_FROM_ENTITY, // 0x23
|
||||
PING_REQUEST, // 0x24
|
||||
PLACE_RECIPE, // 0x25
|
||||
PLAYER_ABILITIES, // 0x26
|
||||
PLAYER_ACTION, // 0x27
|
||||
PLAYER_COMMAND, // 0x28
|
||||
PLAYER_INPUT, // 0x29
|
||||
PLAYER_LOADED, // 0x2A
|
||||
PONG, // 0x2B
|
||||
RECIPE_BOOK_CHANGE_SETTINGS, // 0x2C
|
||||
RECIPE_BOOK_SEEN_RECIPE, // 0x2D
|
||||
RENAME_ITEM, // 0x2E
|
||||
RESOURCE_PACK, // 0x2F
|
||||
SEEN_ADVANCEMENTS, // 0x30
|
||||
SELECT_TRADE, // 0x31
|
||||
SET_BEACON, // 0x32
|
||||
SET_CARRIED_ITEM, // 0x33
|
||||
SET_COMMAND_BLOCK, // 0x34
|
||||
SET_COMMAND_MINECART, // 0x35
|
||||
SET_CREATIVE_MODE_SLOT, // 0x36
|
||||
SET_JIGSAW_BLOCK, // 0x37
|
||||
SET_STRUCTURE_BLOCK, // 0x38
|
||||
SIGN_UPDATE, // 0x39
|
||||
SWING, // 0x3A
|
||||
TELEPORT_TO_ENTITY, // 0x3B
|
||||
USE_ITEM_ON, // 0x3C
|
||||
USE_ITEM; // 0x3D
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
+31
@@ -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.protocols.v1_21_2to1_21_4.provider;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.api.platform.providers.Provider;
|
||||
|
||||
public class PickItemProvider implements Provider {
|
||||
|
||||
public void pickItemFromBlock(final UserConnection connection, final BlockPosition blockPosition, final boolean includeData) {
|
||||
}
|
||||
|
||||
public void pickItemFromEntity(final UserConnection connection, final int entityId, final boolean includeData) {
|
||||
}
|
||||
}
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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_21_2to1_21_4.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.IntTag;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
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.CustomModelData1_21_4;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPacket1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.provider.PickItemProvider;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
|
||||
public final class BlockItemPacketRewriter1_21_4 extends StructuredItemRewriter<ClientboundPacket1_21_2, ServerboundPacket1_21_4, Protocol1_21_2To1_21_4> {
|
||||
|
||||
public BlockItemPacketRewriter1_21_4(final Protocol1_21_2To1_21_4 protocol) {
|
||||
super(protocol,
|
||||
Types1_21_2.ITEM, Types1_21_2.ITEM_ARRAY, Types1_21_4.ITEM, Types1_21_4.ITEM_ARRAY,
|
||||
Types1_21_2.ITEM_COST, Types1_21_2.OPTIONAL_ITEM_COST, Types1_21_4.ITEM_COST, Types1_21_4.OPTIONAL_ITEM_COST
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPackets() {
|
||||
final BlockRewriter<ClientboundPacket1_21_2> blockRewriter = BlockRewriter.for1_20_2(protocol);
|
||||
blockRewriter.registerBlockEvent(ClientboundPackets1_21_2.BLOCK_EVENT);
|
||||
blockRewriter.registerBlockUpdate(ClientboundPackets1_21_2.BLOCK_UPDATE);
|
||||
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21_2.SECTION_BLOCKS_UPDATE);
|
||||
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21_2.LEVEL_EVENT, 2001);
|
||||
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21_2.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
|
||||
blockRewriter.registerBlockEntityData(ClientboundPackets1_21_2.BLOCK_ENTITY_DATA);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.SET_HELD_SLOT, wrapper -> {
|
||||
final byte slot = wrapper.read(Types.BYTE);
|
||||
wrapper.write(Types.VAR_INT, (int) slot);
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_21_4.PICK_ITEM_FROM_BLOCK, null, wrapper -> {
|
||||
final BlockPosition blockPosition = wrapper.read(Types.BLOCK_POSITION1_14);
|
||||
final boolean includeData = wrapper.read(Types.BOOLEAN);
|
||||
Via.getManager().getProviders().get(PickItemProvider.class).pickItemFromBlock(wrapper.user(), blockPosition, includeData);
|
||||
wrapper.cancel();
|
||||
});
|
||||
protocol.registerServerbound(ServerboundPackets1_21_4.PICK_ITEM_FROM_ENTITY, null, wrapper -> {
|
||||
final int entityId = wrapper.read(Types.VAR_INT);
|
||||
final boolean includeData = wrapper.read(Types.BOOLEAN);
|
||||
Via.getManager().getProviders().get(PickItemProvider.class).pickItemFromEntity(wrapper.user(), entityId, includeData);
|
||||
wrapper.cancel();
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
|
||||
registerSetPlayerInventory(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY);
|
||||
registerCooldown1_21_2(ClientboundPackets1_21_2.COOLDOWN);
|
||||
registerSetContent1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT);
|
||||
registerSetSlot1_21_2(ClientboundPackets1_21_2.CONTAINER_SET_SLOT);
|
||||
registerAdvancements1_20_3(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS);
|
||||
registerSetEquipment(ClientboundPackets1_21_2.SET_EQUIPMENT);
|
||||
registerContainerClick1_21_2(ServerboundPackets1_21_4.CONTAINER_CLICK);
|
||||
registerMerchantOffers1_20_5(ClientboundPackets1_21_2.MERCHANT_OFFERS);
|
||||
registerSetCreativeModeSlot(ServerboundPackets1_21_4.SET_CREATIVE_MODE_SLOT);
|
||||
|
||||
final RecipeDisplayRewriter<ClientboundPacket1_21_2> recipeRewriter = new RecipeDisplayRewriter<>(protocol);
|
||||
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_2.UPDATE_RECIPES);
|
||||
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_2.RECIPE_BOOK_ADD);
|
||||
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item handleItemToClient(final UserConnection connection, final Item item) {
|
||||
super.handleItemToClient(connection, item);
|
||||
|
||||
final StructuredDataContainer dataContainer = item.dataContainer();
|
||||
final Integer modelData = dataContainer.get(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5);
|
||||
if (modelData != null) {
|
||||
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4(
|
||||
new float[]{modelData.floatValue()},
|
||||
new boolean[0],
|
||||
new String[0],
|
||||
new int[0]
|
||||
));
|
||||
saveTag(createCustomTag(item), new IntTag(modelData), "custom_model_data");
|
||||
}
|
||||
|
||||
updateItemData(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item handleItemToServer(final UserConnection connection, final Item item) {
|
||||
super.handleItemToServer(connection, item);
|
||||
|
||||
final StructuredDataContainer dataContainer = item.dataContainer();
|
||||
final CompoundTag customData = dataContainer.get(StructuredDataKey.CUSTOM_DATA);
|
||||
if (customData != null) {
|
||||
if (customData.remove(nbtTagName("custom_model_data")) instanceof final IntTag customModelData) {
|
||||
dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, customModelData.asInt());
|
||||
removeCustomTag(dataContainer, customData);
|
||||
}
|
||||
}
|
||||
|
||||
downgradeItemData(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
public static void updateItemData(final Item item) {
|
||||
final StructuredDataContainer dataContainer = item.dataContainer();
|
||||
dataContainer.replaceKey(StructuredDataKey.CHARGED_PROJECTILES1_21_2, StructuredDataKey.CHARGED_PROJECTILES1_21_4);
|
||||
dataContainer.replaceKey(StructuredDataKey.BUNDLE_CONTENTS1_21_2, StructuredDataKey.BUNDLE_CONTENTS1_21_4);
|
||||
dataContainer.replaceKey(StructuredDataKey.CONTAINER1_21_2, StructuredDataKey.CONTAINER1_21_4);
|
||||
dataContainer.replaceKey(StructuredDataKey.USE_REMAINDER1_21_2, StructuredDataKey.USE_REMAINDER1_21_4);
|
||||
dataContainer.replaceKey(StructuredDataKey.TRIM1_21_2, StructuredDataKey.TRIM1_21_4);
|
||||
dataContainer.remove(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5);
|
||||
}
|
||||
|
||||
public static void downgradeItemData(final Item item) {
|
||||
final StructuredDataContainer dataContainer = item.dataContainer();
|
||||
dataContainer.replaceKey(StructuredDataKey.CHARGED_PROJECTILES1_21_4, StructuredDataKey.CHARGED_PROJECTILES1_21_2);
|
||||
dataContainer.replaceKey(StructuredDataKey.BUNDLE_CONTENTS1_21_4, StructuredDataKey.BUNDLE_CONTENTS1_21_2);
|
||||
dataContainer.replaceKey(StructuredDataKey.CONTAINER1_21_4, StructuredDataKey.CONTAINER1_21_2);
|
||||
dataContainer.replaceKey(StructuredDataKey.USE_REMAINDER1_21_4, StructuredDataKey.USE_REMAINDER1_21_2);
|
||||
dataContainer.replaceKey(StructuredDataKey.TRIM1_21_4, StructuredDataKey.TRIM1_21_2);
|
||||
dataContainer.remove(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4);
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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_21_2to1_21_4.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.util.SerializerVersion;
|
||||
import com.viaversion.viaversion.util.TagUtil;
|
||||
|
||||
public final class ComponentRewriter1_21_4 extends ComponentRewriter<ClientboundPacket1_21_2> {
|
||||
|
||||
public ComponentRewriter1_21_4(final Protocol1_21_2To1_21_4 protocol) {
|
||||
super(protocol, ReadType.NBT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
|
||||
super.handleShowItem(connection, itemTag, componentsTag);
|
||||
if (componentsTag == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TagUtil.removeNamespaced(componentsTag, "custom_model_data");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializerVersion inputSerializerVersion() {
|
||||
return SerializerVersion.V1_20_5;
|
||||
}
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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_21_2to1_21_4.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_4;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.Protocol1_21_2To1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21_2to1_21_4.packet.ServerboundPackets1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
|
||||
public final class EntityPacketRewriter1_21_4 extends EntityRewriter<ClientboundPacket1_21_2, Protocol1_21_2To1_21_4> {
|
||||
|
||||
public EntityPacketRewriter1_21_4(final Protocol1_21_2To1_21_4 protocol) {
|
||||
super(protocol);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPackets() {
|
||||
registerTrackerWithData1_19(ClientboundPackets1_21_2.ADD_ENTITY, EntityTypes1_21_4.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets1_21_2.SET_ENTITY_DATA, Types1_21_2.ENTITY_DATA_LIST, Types1_21_4.ENTITY_DATA_LIST);
|
||||
registerRemoveEntities(ClientboundPackets1_21_2.REMOVE_ENTITIES);
|
||||
|
||||
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol) {
|
||||
@Override
|
||||
public RegistryEntry[] handle(final UserConnection connection, final String key, final RegistryEntry[] entries) {
|
||||
if (Key.stripMinecraftNamespace(key).equals("worldgen/biome")) {
|
||||
for (final RegistryEntry entry : entries) {
|
||||
if (entry.tag() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final CompoundTag effectsTag = ((CompoundTag) entry.tag()).getCompoundTag("effects");
|
||||
final CompoundTag musicTag = effectsTag.getCompoundTag("music");
|
||||
if (musicTag == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wrap music
|
||||
final ListTag<CompoundTag> weightedMusicTags = new ListTag<>(CompoundTag.class);
|
||||
final CompoundTag weightedMusicTag = new CompoundTag();
|
||||
weightedMusicTag.put("data", musicTag);
|
||||
weightedMusicTag.putInt("weight", 1);
|
||||
weightedMusicTags.add(weightedMusicTag);
|
||||
effectsTag.put("music", weightedMusicTags);
|
||||
}
|
||||
}
|
||||
|
||||
return super.handle(connection, key, entries);
|
||||
}
|
||||
};
|
||||
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, registryDataRewriter::handle);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.LOGIN, wrapper -> {
|
||||
final int entityId = wrapper.passthrough(Types.INT); // Entity id
|
||||
wrapper.passthrough(Types.BOOLEAN); // Hardcore
|
||||
wrapper.passthrough(Types.STRING_ARRAY); // World List
|
||||
wrapper.passthrough(Types.VAR_INT); // Max players
|
||||
wrapper.passthrough(Types.VAR_INT); // View distance
|
||||
wrapper.passthrough(Types.VAR_INT); // Simulation distance
|
||||
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show death screen
|
||||
wrapper.passthrough(Types.BOOLEAN); // Limited crafting
|
||||
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
|
||||
|
||||
trackPlayer(wrapper.user(), entityId);
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_21_2.RESPAWN, wrapper -> {
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
|
||||
});
|
||||
|
||||
protocol.registerServerbound(ServerboundPackets1_21_4.MOVE_VEHICLE, wrapper -> {
|
||||
wrapper.passthrough(Types.DOUBLE); // X
|
||||
wrapper.passthrough(Types.DOUBLE); // Y
|
||||
wrapper.passthrough(Types.DOUBLE); // Z
|
||||
wrapper.passthrough(Types.FLOAT); // Yaw
|
||||
wrapper.passthrough(Types.FLOAT); // Pitch
|
||||
wrapper.read(Types.BOOLEAN); // On ground
|
||||
});
|
||||
protocol.cancelServerbound(ServerboundPackets1_21_4.PLAYER_LOADED);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
filter().mapDataType(Types1_21_4.ENTITY_DATA_TYPES::byId);
|
||||
|
||||
registerEntityDataTypeHandler(
|
||||
Types1_21_4.ENTITY_DATA_TYPES.itemType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.blockStateType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.optionalBlockStateType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.particleType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.particlesType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.componentType,
|
||||
Types1_21_4.ENTITY_DATA_TYPES.optionalComponentType
|
||||
);
|
||||
registerBlockStateHandler(EntityTypes1_21_4.ABSTRACT_MINECART, 11);
|
||||
|
||||
filter().type(EntityTypes1_21_4.CREAKING).addIndex(18); // Is tearing down
|
||||
filter().type(EntityTypes1_21_4.SALMON).index(17).handler((event, data) -> {
|
||||
final String type = data.value();
|
||||
final int typeId = switch (type) {
|
||||
case "small" -> 0;
|
||||
case "large" -> 2;
|
||||
default -> 1; // medium
|
||||
};
|
||||
data.setTypeAndValue(Types1_21_4.ENTITY_DATA_TYPES.varIntType, typeId);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMappingDataLoaded() {
|
||||
mapTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType typeFromId(final int type) {
|
||||
return EntityTypes1_21_4.getTypeFromId(type);
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.v1_21_2to1_21_4.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPacket1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.ParticleRewriter;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public final class ParticleRewriter1_21_4 extends ParticleRewriter<ClientboundPacket1_21_2> {
|
||||
|
||||
public ParticleRewriter1_21_4(final Protocol<ClientboundPacket1_21_2, ?, ?, ?> protocol) {
|
||||
super(protocol, Types1_21_2.PARTICLE, Types1_21_4.PARTICLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rewriteParticle(final UserConnection connection, final Particle particle) {
|
||||
super.rewriteParticle(connection, particle);
|
||||
|
||||
final String identifier = protocol.getMappingData().getParticleMappings().mappedIdentifier(particle.id());
|
||||
if ("minecraft:trail".equals(identifier)) {
|
||||
// Duration
|
||||
particle.add(Types.VAR_INT, ThreadLocalRandom.current().nextInt(40) + 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
-7
@@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
|
||||
@@ -171,7 +172,8 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol<ClientboundPack
|
||||
registerClientbound(ClientboundPackets1_21.BUNDLE_DELIMITER, wrapper -> wrapper.user().get(BundleStateTracker.class).toggleBundling());
|
||||
registerServerbound(ServerboundPackets1_21_2.PONG, wrapper -> {
|
||||
final int id = wrapper.passthrough(Types.INT); // id
|
||||
if (wrapper.user().get(PlayerPositionStorage.class).checkPong(id)) {
|
||||
final PlayerPositionStorage playerPositionStorage = wrapper.user().get(PlayerPositionStorage.class);
|
||||
if (playerPositionStorage != null && playerPositionStorage.checkPong(id)) {
|
||||
wrapper.cancel();
|
||||
}
|
||||
});
|
||||
@@ -204,17 +206,17 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol<ClientboundPack
|
||||
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
|
||||
.reader("shriek", ParticleType.Readers.SHRIEK)
|
||||
.reader("entity_effect", ParticleType.Readers.COLOR)
|
||||
.reader("trail", ParticleType.Readers.TRAIL)
|
||||
.reader("trail", ParticleType.Readers.TRAIL1_21_2)
|
||||
.reader("item", ParticleType.Readers.item(Types1_21_2.ITEM));
|
||||
Types1_21_2.STRUCTURED_DATA.filler(this).add(StructuredDataKey.CUSTOM_DATA, StructuredDataKey.MAX_STACK_SIZE, StructuredDataKey.MAX_DAMAGE,
|
||||
StructuredDataKey.UNBREAKABLE, StructuredDataKey.RARITY, StructuredDataKey.HIDE_TOOLTIP, StructuredDataKey.DAMAGE_RESISTANT,
|
||||
StructuredDataKey.CUSTOM_NAME, StructuredDataKey.LORE, StructuredDataKey.ENCHANTMENTS, StructuredDataKey.CAN_PLACE_ON,
|
||||
StructuredDataKey.CAN_BREAK, StructuredDataKey.CUSTOM_MODEL_DATA, StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP,
|
||||
StructuredDataKey.CAN_BREAK, StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP,
|
||||
StructuredDataKey.REPAIR_COST, StructuredDataKey.CREATIVE_SLOT_LOCK, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE,
|
||||
StructuredDataKey.INTANGIBLE_PROJECTILE, StructuredDataKey.STORED_ENCHANTMENTS, StructuredDataKey.DYED_COLOR,
|
||||
StructuredDataKey.MAP_COLOR, StructuredDataKey.MAP_ID, StructuredDataKey.MAP_DECORATIONS, StructuredDataKey.MAP_POST_PROCESSING,
|
||||
StructuredDataKey.POTION_CONTENTS1_21_2, StructuredDataKey.SUSPICIOUS_STEW_EFFECTS, StructuredDataKey.WRITABLE_BOOK_CONTENT,
|
||||
StructuredDataKey.WRITTEN_BOOK_CONTENT, StructuredDataKey.TRIM, StructuredDataKey.DEBUG_STICK_STATE, StructuredDataKey.ENTITY_DATA,
|
||||
StructuredDataKey.WRITTEN_BOOK_CONTENT, StructuredDataKey.TRIM1_21_2, StructuredDataKey.DEBUG_STICK_STATE, StructuredDataKey.ENTITY_DATA,
|
||||
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA, StructuredDataKey.INSTRUMENT1_21_2,
|
||||
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
|
||||
StructuredDataKey.PROFILE, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
|
||||
@@ -225,7 +227,7 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol<ClientboundPack
|
||||
StructuredDataKey.USE_COOLDOWN, StructuredDataKey.DAMAGE, StructuredDataKey.EQUIPPABLE, StructuredDataKey.ITEM_MODEL,
|
||||
StructuredDataKey.GLIDER, StructuredDataKey.TOOLTIP_STYLE, StructuredDataKey.DEATH_PROTECTION,
|
||||
// Volatile thanks to containing item
|
||||
StructuredDataKey.CHARGED_PROJECTILES1_21_2, StructuredDataKey.BUNDLE_CONTENTS1_21_2, StructuredDataKey.CONTAINER1_21_2, StructuredDataKey.USE_REMAINDER);
|
||||
StructuredDataKey.CHARGED_PROJECTILES1_21_2, StructuredDataKey.BUNDLE_CONTENTS1_21_2, StructuredDataKey.CONTAINER1_21_2, StructuredDataKey.USE_REMAINDER1_21_2);
|
||||
super.onMappingDataLoaded();
|
||||
}
|
||||
|
||||
@@ -233,9 +235,19 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol<ClientboundPack
|
||||
public void init(final UserConnection connection) {
|
||||
addEntityTracker(connection, new EntityTracker1_21_2(connection));
|
||||
connection.put(new BundleStateTracker());
|
||||
connection.put(new PlayerPositionStorage());
|
||||
connection.put(new ChunkLoadTracker());
|
||||
connection.put(new GroundFlagTracker());
|
||||
|
||||
final ProtocolVersion protocolVersion = connection.getProtocolInfo().protocolVersion();
|
||||
if (protocolVersion.olderThan(ProtocolVersion.v1_21_4)) { // Only needed for 1.21.2/1.21.3
|
||||
connection.put(new PlayerPositionStorage());
|
||||
}
|
||||
|
||||
// <= 1.21.1 clients allowed loaded chunks to get replaced with new data without unloading them first.
|
||||
// 1.21.2 introduced a graphical bug where it doesn't properly render the new data unless the chunk is unloaded beforehand.
|
||||
// 1.21.4 fixed this bug, so the workaround is no longer needed.
|
||||
if (protocolVersion.equals(ProtocolVersion.v1_21_2)) {
|
||||
connection.put(new ChunkLoadTracker());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+37
-6
@@ -65,6 +65,7 @@ import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.Limit;
|
||||
import com.viaversion.viaversion.util.SerializerVersion;
|
||||
import com.viaversion.viaversion.util.TagUtil;
|
||||
import com.viaversion.viaversion.util.Unit;
|
||||
@@ -154,7 +155,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
wrapper.passthrough(Types.SHORT); // Slot
|
||||
wrapper.passthrough(Types.BYTE); // Button
|
||||
wrapper.passthrough(Types.VAR_INT); // Mode
|
||||
final int length = wrapper.passthrough(Types.VAR_INT);
|
||||
final int length = Limit.max(wrapper.passthrough(Types.VAR_INT), 128);
|
||||
for (int i = 0; i < length; i++) {
|
||||
wrapper.passthrough(Types.SHORT); // Slot
|
||||
passthroughServerboundItem(wrapper);
|
||||
@@ -375,6 +376,10 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
}
|
||||
|
||||
final ChunkLoadTracker chunkLoadTracker = wrapper.user().get(ChunkLoadTracker.class);
|
||||
if (chunkLoadTracker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chunkLoadTracker.isChunkLoaded(chunk.getX(), chunk.getZ())) {
|
||||
// Unload the old chunk, so the new one can be loaded without graphical glitches
|
||||
// Bundling it prevents the client from falling through the world during the chunk swap
|
||||
@@ -400,7 +405,11 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
});
|
||||
protocol.registerClientbound(ClientboundPackets1_21.FORGET_LEVEL_CHUNK, wrapper -> {
|
||||
final ChunkPosition chunkPosition = wrapper.passthrough(Types.CHUNK_POSITION);
|
||||
wrapper.user().get(ChunkLoadTracker.class).removeChunk(chunkPosition.chunkX(), chunkPosition.chunkZ());
|
||||
|
||||
final ChunkLoadTracker chunkLoadTracker = wrapper.user().get(ChunkLoadTracker.class);
|
||||
if (chunkLoadTracker != null) {
|
||||
chunkLoadTracker.removeChunk(chunkPosition.chunkX(), chunkPosition.chunkZ());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -422,12 +431,20 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
}
|
||||
|
||||
super.handleItemToClient(connection, item);
|
||||
|
||||
// Handle food properties item manually here - the only protocol that has it
|
||||
// The other way around it's handled by the super handleItemToServer method
|
||||
final StructuredDataContainer data = item.dataContainer();
|
||||
final FoodProperties1_20_5 food = data.get(StructuredDataKey.FOOD1_21);
|
||||
if (food != null && food.usingConvertsTo() != null) {
|
||||
this.handleItemToClient(connection, food.usingConvertsTo());
|
||||
}
|
||||
|
||||
updateItemData(item);
|
||||
|
||||
// Add data components to fix issues in older protocols
|
||||
appendItemDataFixComponents(connection, item);
|
||||
|
||||
final StructuredDataContainer data = item.dataContainer();
|
||||
final Enchantments enchantments = data.get(StructuredDataKey.ENCHANTMENTS);
|
||||
if (enchantments != null && enchantments.size() != 0) {
|
||||
// Level 0 is no longer allowed
|
||||
@@ -552,7 +569,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
|
||||
dataContainer.set(StructuredDataKey.CONSUMABLE1_21_2, new Consumable1_21_2(food.eatSeconds(), 1 /* eat */, sound, true, consumeEffects));
|
||||
if (food.usingConvertsTo() != null) {
|
||||
dataContainer.set(StructuredDataKey.USE_REMAINDER, food.usingConvertsTo());
|
||||
dataContainer.set(StructuredDataKey.USE_REMAINDER1_21_2, food.usingConvertsTo());
|
||||
}
|
||||
return new FoodProperties1_21_2(food.nutrition(), food.saturationModifier(), food.canAlwaysEat());
|
||||
});
|
||||
@@ -570,6 +587,13 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
itemComponentsTag.putString("custom_name", ComponentUtil.plainToJson(lock).toString());
|
||||
return predicateTag;
|
||||
});
|
||||
dataContainer.replace(StructuredDataKey.TRIM1_20_5, StructuredDataKey.TRIM1_21_2, trim -> {
|
||||
// TODO Rewrite from int to string id via sent registry
|
||||
if (trim.material().isDirect()) {
|
||||
trim.material().value().overrideArmorMaterials().clear();
|
||||
}
|
||||
return trim;
|
||||
});
|
||||
}
|
||||
|
||||
public static void downgradeItemData(final Item item) {
|
||||
@@ -593,7 +617,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
});
|
||||
dataContainer.replace(StructuredDataKey.FOOD1_21_2, StructuredDataKey.FOOD1_21, food -> {
|
||||
final Consumable1_21_2 consumableData = dataContainer.get(StructuredDataKey.CONSUMABLE1_21_2);
|
||||
final Item useRemainderData = dataContainer.get(StructuredDataKey.USE_REMAINDER);
|
||||
final Item useRemainderData = dataContainer.get(StructuredDataKey.USE_REMAINDER1_21_2);
|
||||
final float eatSeconds = consumableData != null ? consumableData.consumeSeconds() : 1.6F;
|
||||
final List<FoodProperties1_20_5.FoodEffect> foodEffects = new ArrayList<>();
|
||||
if (consumableData != null) {
|
||||
@@ -607,6 +631,13 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
}
|
||||
return new FoodProperties1_20_5(food.nutrition(), food.saturationModifier(), food.canAlwaysEat(), eatSeconds, useRemainderData, foodEffects.toArray(new FoodProperties1_20_5.FoodEffect[0]));
|
||||
});
|
||||
dataContainer.replace(StructuredDataKey.TRIM1_21_2, StructuredDataKey.TRIM1_20_5, trim -> {
|
||||
// TODO
|
||||
if (trim.material().isDirect()) {
|
||||
trim.material().value().overrideArmorMaterials().clear();
|
||||
}
|
||||
return trim;
|
||||
});
|
||||
dataContainer.replaceKey(StructuredDataKey.CONTAINER1_21_2, StructuredDataKey.CONTAINER1_21);
|
||||
dataContainer.replaceKey(StructuredDataKey.CHARGED_PROJECTILES1_21_2, StructuredDataKey.CHARGED_PROJECTILES1_21);
|
||||
dataContainer.replaceKey(StructuredDataKey.BUNDLE_CONTENTS1_21_2, StructuredDataKey.BUNDLE_CONTENTS1_21);
|
||||
@@ -620,7 +651,7 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
|
||||
dataContainer.remove(StructuredDataKey.REPAIRABLE);
|
||||
dataContainer.remove(StructuredDataKey.ENCHANTABLE);
|
||||
dataContainer.remove(StructuredDataKey.CONSUMABLE1_21_2);
|
||||
dataContainer.remove(StructuredDataKey.USE_REMAINDER);
|
||||
dataContainer.remove(StructuredDataKey.USE_REMAINDER1_21_2);
|
||||
dataContainer.remove(StructuredDataKey.USE_COOLDOWN);
|
||||
dataContainer.remove(StructuredDataKey.ITEM_MODEL);
|
||||
dataContainer.remove(StructuredDataKey.EQUIPPABLE);
|
||||
|
||||
+13
-5
@@ -159,7 +159,10 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
|
||||
final EntityTracker entityTracker = tracker(wrapper.user());
|
||||
if (entityTracker.currentWorld() != null && !entityTracker.currentWorld().equals(world)) {
|
||||
wrapper.user().get(ChunkLoadTracker.class).clear();
|
||||
final ChunkLoadTracker chunkLoadTracker = wrapper.user().get(ChunkLoadTracker.class);
|
||||
if (chunkLoadTracker != null) {
|
||||
chunkLoadTracker.clear();
|
||||
}
|
||||
}
|
||||
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world);
|
||||
@@ -197,6 +200,11 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
final int teleportId = wrapper.read(Types.VAR_INT);
|
||||
wrapper.set(Types.VAR_INT, 0, teleportId);
|
||||
|
||||
final PlayerPositionStorage positionStorage = wrapper.user().get(PlayerPositionStorage.class);
|
||||
if (positionStorage == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Accept teleportation and player position were swapped.
|
||||
// Send a ping first to then capture and send the player position the accept teleportation
|
||||
final boolean isBundling = wrapper.user().get(BundleStateTracker.class).isBundling();
|
||||
@@ -206,7 +214,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
}
|
||||
|
||||
final int pingId = ThreadLocalRandom.current().nextInt();
|
||||
wrapper.user().get(PlayerPositionStorage.class).addPendingPong(pingId);
|
||||
positionStorage.addPendingPong(pingId);
|
||||
final PacketWrapper ping = wrapper.create(ClientboundPackets1_21_2.PING);
|
||||
ping.write(Types.INT, pingId); // id
|
||||
ping.send(Protocol1_21To1_21_2.class);
|
||||
@@ -327,7 +335,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
handleOnGround(wrapper);
|
||||
|
||||
final PlayerPositionStorage playerPositionStorage = wrapper.user().get(PlayerPositionStorage.class);
|
||||
if (playerPositionStorage.checkCaptureNextPlayerPositionPacket()) {
|
||||
if (playerPositionStorage != null && playerPositionStorage.checkCaptureNextPlayerPositionPacket()) {
|
||||
// Capture this packet and send it after accept teleportation
|
||||
final boolean onGround = wrapper.get(Types.BOOLEAN, 0);
|
||||
playerPositionStorage.setPlayerPosition(new PlayerPositionStorage.PlayerPosition(x, y, z, yaw, pitch, onGround));
|
||||
@@ -352,7 +360,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
});
|
||||
protocol.registerServerbound(ServerboundPackets1_21_2.ACCEPT_TELEPORTATION, wrapper -> {
|
||||
final PlayerPositionStorage playerPositionStorage = wrapper.user().get(PlayerPositionStorage.class);
|
||||
if (playerPositionStorage.checkHasPlayerPosition()) {
|
||||
if (playerPositionStorage != null && playerPositionStorage.checkHasPlayerPosition()) {
|
||||
// Send move player after accept teleportation
|
||||
wrapper.sendToServer(Protocol1_21To1_21_2.class);
|
||||
wrapper.cancel();
|
||||
@@ -453,7 +461,7 @@ public final class EntityPacketRewriter1_21_2 extends EntityRewriter<Clientbound
|
||||
|
||||
// Remove old entity
|
||||
final PacketWrapper removeEntityPacket = PacketWrapper.create(ClientboundPackets1_21_2.REMOVE_ENTITIES, event.user());
|
||||
removeEntityPacket.write(Types.VAR_INT_ARRAY_PRIMITIVE, new int[] { event.entityId() });
|
||||
removeEntityPacket.write(Types.VAR_INT_ARRAY_PRIMITIVE, new int[]{event.entityId()});
|
||||
removeEntityPacket.send(Protocol1_21To1_21_2.class);
|
||||
|
||||
// Detect correct boat entity type from entity data
|
||||
|
||||
+3
-3
@@ -43,12 +43,12 @@ public final class ParticleRewriter1_21_2 extends ParticleRewriter<ClientboundPa
|
||||
@Override
|
||||
public void rewriteParticle(final UserConnection connection, final Particle particle) {
|
||||
super.rewriteParticle(connection, particle);
|
||||
|
||||
|
||||
final String identifier = protocol.getMappingData().getParticleMappings().mappedIdentifier(particle.id());
|
||||
if (identifier.equals("minecraft:dust_color_transition")) {
|
||||
if ("minecraft:dust_color_transition".equals(identifier)) {
|
||||
floatsToARGB(particle, 0);
|
||||
floatsToARGB(particle, 1);
|
||||
} else if (identifier.equals("minecraft:dust")) {
|
||||
} else if ("minecraft:dust".equals(identifier)) {
|
||||
floatsToARGB(particle, 0);
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -327,6 +327,10 @@ final class RecipeRewriter1_21_2 extends RecipeRewriter1_20_3<ClientboundPacket1
|
||||
wrapper.write(Types.VAR_INT, Recipe.SLOT_DISPLAY_EMPTY);
|
||||
return;
|
||||
}
|
||||
if (ingredient.length == 1) {
|
||||
writeItemDisplay(wrapper, ingredient[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.write(Types.VAR_INT, Recipe.SLOT_DISPLAY_COMPOSITE);
|
||||
wrapper.write(Types.VAR_INT, ingredient.length);
|
||||
|
||||
+10
-28
@@ -21,53 +21,35 @@ import com.viaversion.nbt.tag.ByteTag;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import com.viaversion.viaversion.api.minecraft.BlockPosition;
|
||||
import com.viaversion.viaversion.util.Pair;
|
||||
import com.viaversion.viaversion.api.minecraft.ChunkPosition;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class CommandBlockStorage implements StorableObject {
|
||||
private final Map<Pair<Integer, Integer>, Map<BlockPosition, CompoundTag>> storedCommandBlocks = new HashMap<>();
|
||||
private final Map<Long, Map<BlockPosition, CompoundTag>> storedCommandBlocks = new HashMap<>();
|
||||
private boolean permissions;
|
||||
|
||||
public void unloadChunk(int x, int z) {
|
||||
Pair<Integer, Integer> chunkPos = new Pair<>(x, z);
|
||||
storedCommandBlocks.remove(chunkPos);
|
||||
storedCommandBlocks.remove(ChunkPosition.chunkKey(x, z));
|
||||
}
|
||||
|
||||
public void addOrUpdateBlock(BlockPosition position, CompoundTag tag) {
|
||||
Pair<Integer, Integer> chunkPos = getChunkCoords(position);
|
||||
|
||||
if (!storedCommandBlocks.containsKey(chunkPos)) {
|
||||
storedCommandBlocks.put(chunkPos, new HashMap<>());
|
||||
}
|
||||
|
||||
Map<BlockPosition, CompoundTag> blocks = storedCommandBlocks.get(chunkPos);
|
||||
|
||||
if (blocks.containsKey(position) && blocks.get(position).equals(tag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
long chunkKey = ChunkPosition.chunkKeyForBlock(position.x(), position.z());
|
||||
Map<BlockPosition, CompoundTag> blocks = storedCommandBlocks.computeIfAbsent(chunkKey, k -> new HashMap<>());
|
||||
blocks.put(position, tag);
|
||||
}
|
||||
|
||||
private Pair<Integer, Integer> getChunkCoords(BlockPosition position) {
|
||||
int chunkX = Math.floorDiv(position.x(), 16);
|
||||
int chunkZ = Math.floorDiv(position.z(), 16);
|
||||
|
||||
return new Pair<>(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
public Optional<CompoundTag> getCommandBlock(BlockPosition position) {
|
||||
Pair<Integer, Integer> chunkCoords = getChunkCoords(position);
|
||||
|
||||
Map<BlockPosition, CompoundTag> blocks = storedCommandBlocks.get(chunkCoords);
|
||||
if (blocks == null)
|
||||
Map<BlockPosition, CompoundTag> blocks = storedCommandBlocks.get(ChunkPosition.chunkKeyForBlock(position.x(), position.z()));
|
||||
if (blocks == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
CompoundTag tag = blocks.get(position);
|
||||
if (tag == null)
|
||||
if (tag == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
tag = tag.copy();
|
||||
tag.put("powered", new ByteTag((byte) 0));
|
||||
|
||||
@@ -67,11 +67,11 @@ public class BlockRewriter<C extends ClientboundPacketType> {
|
||||
}
|
||||
|
||||
public void registerBlockEvent(C packetType) {
|
||||
if (protocol.getMappingData().getBlockMappings() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
if (protocol.getMappingData().getBlockMappings() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.passthrough(positionType); // Location
|
||||
wrapper.passthrough(Types.UNSIGNED_BYTE); // Action id
|
||||
wrapper.passthrough(Types.UNSIGNED_BYTE); // Action param
|
||||
|
||||
@@ -165,9 +165,9 @@ public class ComponentRewriter<C extends ClientboundPacketType> implements com.v
|
||||
});
|
||||
}
|
||||
|
||||
public void registerPlayerInfoUpdate1_21_2(final C packetType) {
|
||||
public void registerPlayerInfoUpdate1_21_4(final C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
final BitSet actions = wrapper.passthrough(Types.PROFILE_ACTIONS_ENUM1_21_2);
|
||||
final BitSet actions = wrapper.passthrough(Types.PROFILE_ACTIONS_ENUM1_21_4);
|
||||
if (!actions.get(5)) { // Update display name
|
||||
return;
|
||||
}
|
||||
@@ -204,6 +204,9 @@ public class ComponentRewriter<C extends ClientboundPacketType> implements com.v
|
||||
if (actions.get(6)) {
|
||||
wrapper.passthrough(Types.VAR_INT); // List order
|
||||
}
|
||||
if (actions.get(7)) {
|
||||
wrapper.passthrough(Types.BOOLEAN); // Show hat
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ 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;
|
||||
import com.viaversion.viaversion.util.Limit;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class ItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
|
||||
@@ -219,7 +220,7 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
|
||||
wrapper.passthrough(Types.VAR_INT); // Mode
|
||||
|
||||
// Affected items
|
||||
final int length = wrapper.passthrough(Types.VAR_INT);
|
||||
final int length = Limit.max(wrapper.passthrough(Types.VAR_INT), 128);
|
||||
for (int i = 0; i < length; i++) {
|
||||
wrapper.passthrough(Types.SHORT); // Slot
|
||||
passthroughServerboundItem(wrapper);
|
||||
@@ -230,6 +231,13 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
|
||||
});
|
||||
}
|
||||
|
||||
public void registerSetPlayerInventory(C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
wrapper.passthrough(Types.VAR_INT); // Slot
|
||||
passthroughClientboundItem(wrapper);
|
||||
});
|
||||
}
|
||||
|
||||
public void registerCooldown(C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
int itemId = wrapper.read(Types.VAR_INT);
|
||||
@@ -239,11 +247,11 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
|
||||
|
||||
public void registerCooldown1_21_2(C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
String itemIdentifier = wrapper.read(Types.OPTIONAL_STRING);
|
||||
String itemIdentifier = wrapper.read(Types.STRING);
|
||||
if (itemIdentifier != null) {
|
||||
itemIdentifier = mappedIdentifier(protocol.getMappingData().getFullItemMappings(), itemIdentifier);
|
||||
}
|
||||
wrapper.write(Types.OPTIONAL_STRING, itemIdentifier);
|
||||
wrapper.write(Types.STRING, itemIdentifier);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,25 @@ public class ParticleRewriter<C extends ClientboundPacketType> implements com.vi
|
||||
|
||||
public void registerLevelParticles1_20_5(final C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
wrapper.passthrough(Types.BOOLEAN); // Long Distance
|
||||
wrapper.passthrough(Types.BOOLEAN); // Override limiter
|
||||
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
|
||||
wrapper.passthrough(Types.FLOAT); // Particle Data
|
||||
wrapper.passthrough(Types.INT); // Particle Count
|
||||
|
||||
final Particle particle = wrapper.passthroughAndMap(particleType, mappedParticleType);
|
||||
rewriteParticle(wrapper.user(), particle);
|
||||
});
|
||||
}
|
||||
|
||||
public void registerLevelParticles1_21_4(final C packetType) {
|
||||
protocol.registerClientbound(packetType, wrapper -> {
|
||||
wrapper.passthrough(Types.BOOLEAN); // Override limiter
|
||||
wrapper.passthrough(Types.BOOLEAN); // Always show
|
||||
wrapper.passthrough(Types.DOUBLE); // X
|
||||
wrapper.passthrough(Types.DOUBLE); // Y
|
||||
wrapper.passthrough(Types.DOUBLE); // Z
|
||||
@@ -163,9 +181,11 @@ public class ParticleRewriter<C extends ClientboundPacketType> implements com.vi
|
||||
wrapper.passthrough(Types.DOUBLE); // X
|
||||
wrapper.passthrough(Types.DOUBLE); // Y
|
||||
wrapper.passthrough(Types.DOUBLE); // Z
|
||||
wrapper.passthrough(Types.DOUBLE); // Knockback X
|
||||
wrapper.passthrough(Types.DOUBLE); // Knockback Y
|
||||
wrapper.passthrough(Types.DOUBLE); // Knockback Z
|
||||
if (wrapper.passthrough(Types.BOOLEAN)) {
|
||||
wrapper.passthrough(Types.DOUBLE); // Knockback X
|
||||
wrapper.passthrough(Types.DOUBLE); // Knockback Y
|
||||
wrapper.passthrough(Types.DOUBLE); // Knockback Z
|
||||
}
|
||||
|
||||
final Particle explosionParticle = wrapper.read(particleType);
|
||||
wrapper.write(mappedParticleType, explosionParticle);
|
||||
|
||||
@@ -94,6 +94,8 @@ public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
|
||||
handleSlotDisplay(wrapper); // Fuel
|
||||
handleSlotDisplay(wrapper); // Result
|
||||
handleSlotDisplay(wrapper); // Crafting station
|
||||
wrapper.passthrough(Types.VAR_INT); // Duration
|
||||
wrapper.passthrough(Types.FLOAT); // Experience
|
||||
}
|
||||
|
||||
protected void handleStoneCutter(final PacketWrapper wrapper) {
|
||||
@@ -165,7 +167,7 @@ public class RecipeDisplayRewriter<C extends ClientboundPacketType> {
|
||||
}
|
||||
|
||||
protected void handleItemId(final PacketWrapper wrapper) {
|
||||
final int id = wrapper.passthrough(Types.VAR_INT);
|
||||
final int id = wrapper.read(Types.VAR_INT);
|
||||
wrapper.write(Types.VAR_INT, rewriteItemId(id));
|
||||
}
|
||||
|
||||
|
||||
@@ -108,23 +108,19 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||
for (int i = 0; i < ingredientsNo; i++) {
|
||||
handleIngredient(wrapper);
|
||||
}
|
||||
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
}
|
||||
|
||||
public void handleCraftingShapeless(PacketWrapper wrapper) {
|
||||
wrapper.passthrough(Types.STRING); // Group
|
||||
handleIngredients(wrapper);
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
}
|
||||
|
||||
public void handleSmelting(PacketWrapper wrapper) {
|
||||
wrapper.passthrough(Types.STRING); // Group
|
||||
handleIngredient(wrapper);
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
wrapper.passthrough(Types.FLOAT); // EXP
|
||||
wrapper.passthrough(Types.VAR_INT); // Cooking time
|
||||
}
|
||||
@@ -132,15 +128,13 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||
public void handleStonecutting(PacketWrapper wrapper) {
|
||||
wrapper.passthrough(Types.STRING); // Group
|
||||
handleIngredient(wrapper);
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
}
|
||||
|
||||
public void handleSmithing(PacketWrapper wrapper) {
|
||||
handleIngredient(wrapper); // Base
|
||||
handleIngredient(wrapper); // Addition
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
}
|
||||
|
||||
public void handleSimpleRecipe(final PacketWrapper wrapper) {
|
||||
@@ -151,8 +145,7 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||
handleIngredient(wrapper); // Template
|
||||
handleIngredient(wrapper); // Base
|
||||
handleIngredient(wrapper); // Additions
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
handleResult(wrapper);
|
||||
}
|
||||
|
||||
public void handleSmithingTrim(final PacketWrapper wrapper) {
|
||||
@@ -190,6 +183,11 @@ public class RecipeRewriter<C extends ClientboundPacketType> {
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleResult(final PacketWrapper wrapper) {
|
||||
final Item result = rewrite(wrapper.user(), wrapper.read(itemType()));
|
||||
wrapper.write(mappedItemType(), result);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RecipeConsumer {
|
||||
|
||||
|
||||
@@ -59,6 +59,8 @@ public class RegistryDataRewriter {
|
||||
key = Key.stripMinecraftNamespace(key);
|
||||
if (key.equals("enchantment")) {
|
||||
updateEnchantments(entries);
|
||||
} else if (key.equals("trim_material")) {
|
||||
updateTrimMaterials(entries);
|
||||
}
|
||||
|
||||
final List<RegistryEntry> toAdd = this.toAdd.get(key);
|
||||
@@ -126,6 +128,22 @@ public class RegistryDataRewriter {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTrimMaterials(final RegistryEntry[] entries) {
|
||||
if (protocol.getMappingData().getFullItemMappings() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final RegistryEntry entry : entries) {
|
||||
if (entry.tag() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final StringTag ingredientTag = ((CompoundTag) entry.tag()).getStringTag("ingredient");
|
||||
final String mappedIngredient = protocol.getMappingData().getFullItemMappings().mappedIdentifier(ingredientTag.getValue());
|
||||
ingredientTag.setValue(mappedIngredient);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNestedEffect(final CompoundTag effectsTag) {
|
||||
final CompoundTag effect = effectsTag.getCompoundTag("effect");
|
||||
if (effect == null) {
|
||||
|
||||
@@ -117,7 +117,9 @@ public class StructuredItemRewriter<C extends ClientboundPacketType, S extends S
|
||||
final MappingData mappingData = protocol.getMappingData();
|
||||
if (mappingData.getItemMappings() != null) {
|
||||
final Int2IntFunction itemIdRewriter = clientbound ? mappingData::getNewItemId : mappingData::getOldItemId;
|
||||
container.replace(StructuredDataKey.TRIM, value -> value.rewrite(itemIdRewriter));
|
||||
container.replace(StructuredDataKey.TRIM1_20_5, value -> value.rewrite(itemIdRewriter));
|
||||
container.replace(StructuredDataKey.TRIM1_21_2, value -> value.rewrite(itemIdRewriter));
|
||||
container.replace(StructuredDataKey.TRIM1_21_4, value -> value.rewrite(itemIdRewriter));
|
||||
container.replace(StructuredDataKey.POT_DECORATIONS, value -> value.rewrite(itemIdRewriter));
|
||||
container.replace(StructuredDataKey.REPAIRABLE, value -> value.rewrite(itemIdRewriter));
|
||||
}
|
||||
|
||||
Loaded 100 of 114 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user