Compare commits

..
21 Commits
Author SHA1 Message Date
Nassim Jahnke 1fb3aa8c7a 5.5.1 Release 2025-10-12 18:44:11 +02:00
木葉 Scarlet f175a903a3 Improve some collection usages (#4659) 2025-10-12 18:21:13 +02:00
FlorianMichael 7c80e37e3a Rewrite item ids in 1.12.2->1.13 show_item hover events (#4671) 2025-10-12 18:16:10 +02:00
FlorianMichael ff61e1d897 [ci skip] Update README.md (#4681) 2025-10-12 17:44:30 +02:00
AmirAli Mollaei d49272a41f Fix error when wolf_variant registry data isn't sent in 1.20.5->1.21 (#4655) 2025-10-11 13:01:19 +02:00
Nassim Jahnke bea6df1174 Add april fools snapshot identifiers 2025-10-07 19:44:27 +02:00
Nassim Jahnke 4ca84f6001 Fix <1.13 sounds for VB/VR
Technically unused in VV for now, but may also replace some in-code sound mappings later
2025-10-07 17:42:16 +02:00
Nassim Jahnke 61c079af19 Add 1.21.10 to 1.21.9 version string
No protocol changes
2025-10-07 16:06:55 +02:00
Nassim Jahnke e0b9deb128 Handle repairable item id changes 2025-10-07 15:38:09 +02:00
Nassim Jahnke 1d89bc7f95 Handle deeper lock component changes 2025-10-07 15:23:25 +02:00
dependabot[bot] 28c18c33fa Bump gradle/actions from 4 to 5 (#4678)
Bumps [gradle/actions](https://github.com/gradle/actions) from 4 to 5.
- [Release notes](https://github.com/gradle/actions/releases)
- [Commits](https://github.com/gradle/actions/compare/v4...v5)

---
updated-dependencies:
- dependency-name: gradle/actions
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 23:37:44 +02:00
Nassim Jahnke d08cb1b743 Handle debug sticks with changed blocks/properties 2025-10-06 20:31:14 +02:00
Nassim Jahnke fb18f69a0b Fix world border scale in 1.21.7->1.21.9 2025-10-05 22:05:44 +02:00
Nassim Jahnke 56e1d32aa0 Implement equippable item data hashing 2025-10-05 21:35:35 +02:00
FlorianMichael d4aa5a2fb3 More fixes to team packet filtering in 1.20.3->1.20.5 (#4674) 2025-10-05 21:23:25 +02:00
Nassim Jahnke b54a87f465 Re-shuffle mapping files to reduce size, include sound identifiers 2025-10-05 15:27:32 +02:00
RK_01 5acfa9faf7 Implement 1.21.7 -> 1.21.9 debug sample subscription translation (#4668) 2025-10-05 08:48:42 +02:00
LeonTG 638f4cd19a Fix player team tracking in 1.20.3->1.20.5 packet filtering (#4673) 2025-10-05 03:41:41 +02:00
Nassim Jahnke baf12dd516 Handle particles in biome effects
Fixes #4666
2025-10-04 10:36:17 +02:00
Nassim Jahnke 4b6b26fbba Allow empty block entity mappings in item data 2025-10-03 20:02:06 +02:00
Nassim Jahnke 5c5784795d Bump version to 5.5.1-SNAPSHOT 2025-10-03 20:01:35 +02:00
108 changed files with 1455 additions and 214 deletions

No files matched your search

+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@v5
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
uses: gradle/actions/setup-gradle@v5
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
+2 -4
View File
@@ -8,7 +8,7 @@
it works on any platform you can think of.**
The base ViaVersion jar runs on Paper and Velocity. We also have projects integrating ViaVersion to run
on Fabric, Forge, Bungee, Sponge, or as a standalone proxy to join from basically any client version on
on Fabric, Forge, Sponge, or as a standalone proxy to join from basically any client version on
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\* projects.**
Note that ViaVersion will be able to **run best on either Paper servers or through [ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus?tab=readme-ov-file#viafabricplus)** due to having
@@ -16,7 +16,7 @@ direct access to client/server state and more extensive API.
Supported Versions:
![Table (https://i.imgur.com/zrQTcf0.png)](https://i.imgur.com/zrQTcf0.png)
![Table (https://ci.viaversion.com/userContent/images/T.png)](https://ci.viaversion.com/userContent/images/T.png)
**User Docs:** https://docs.viaversion.com
@@ -87,12 +87,10 @@ of the `build/libs` directory.
You need JDK 17 or newer to build ViaVersion.
Mapping Files
--------------
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings). The generated mapping output is stored [here](./common/src/main/resources/assets/viaversion).
Resources
--------
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.data;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.TagData;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -140,10 +141,14 @@ public interface MappingData {
@Nullable Mappings getBlockMappings();
@Nullable FullMappings getFullBlockMappings();
@Nullable Mappings getBlockStateMappings();
@Nullable Mappings getSoundMappings();
@Nullable FullMappings getFullSoundMappings();
@Nullable Mappings getStatisticsMappings();
@Nullable Mappings getMenuMappings();
@@ -163,4 +168,26 @@ public interface MappingData {
@Nullable FullMappings getRecipeSerializerMappings();
@Nullable FullMappings getDataComponentSerializerMappings();
default @Nullable FullMappings getFullMappings(final MappingType mappingType) {
return switch (mappingType) {
case ITEM -> getFullItemMappings();
case SOUND -> getFullSoundMappings();
case ENTITY -> getEntityMappings();
};
}
/**
* Set of block (not block state) ids that had their base type or properties changed.
*
* @return set of changed block ids, or null if not tracked/none are present
*/
@Nullable IntSet changedBlocks();
/**
* Type of mappings. Currently only relevant for ops writing of generic holder classes and expanded when needed.
*/
enum MappingType {
ITEM, SOUND, ENTITY
}
}
@@ -28,6 +28,8 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.TagData;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
@@ -55,6 +57,10 @@ public class MappingDataBase implements MappingData {
protected Mappings paintingMappings;
protected Mappings menuMappings;
protected Map<RegistryType, List<TagData>> tags;
/**
* Set of block ids that have had type or property changes.
*/
protected IntSet changedBlocks;
public MappingDataBase(final String unmappedVersion, final String mappedVersion) {
this.unmappedVersion = unmappedVersion;
@@ -68,9 +74,7 @@ public class MappingDataBase implements MappingData {
}
final CompoundTag data = readMappingsFile("mappings-" + unmappedVersion + "to" + mappedVersion + ".nbt");
blockMappings = loadBiMappings(data, "blocks");
blockStateMappings = loadMappings(data, "blockstates");
soundMappings = loadMappings(data, "sounds");
statisticsMappings = loadMappings(data, "statistics");
menuMappings = loadMappings(data, "menus");
enchantmentMappings = loadMappings(data, "enchantments");
@@ -79,7 +83,10 @@ public class MappingDataBase implements MappingData {
final CompoundTag unmappedIdentifierData = readUnmappedIdentifiersFile("identifiers-" + unmappedVersion + ".nbt");
final CompoundTag mappedIdentifierData = readMappedIdentifiersFile("identifiers-" + mappedVersion + ".nbt");
if (unmappedIdentifierData != null && mappedIdentifierData != null) {
itemMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "items");
itemMappings = loadFullOrBiMappings(data, unmappedIdentifierData, mappedIdentifierData, "items");
blockMappings = loadFullOrBiMappings(data, unmappedIdentifierData, mappedIdentifierData, "blocks");
soundMappings = loadFullOrBiMappings(data, unmappedIdentifierData, mappedIdentifierData, "sounds");
entityMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "entities");
argumentTypeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "argumenttypes");
recipeSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "recipe_serializers");
@@ -99,6 +106,8 @@ public class MappingDataBase implements MappingData {
} else {
// Might not have identifiers in older versions
itemMappings = loadBiMappings(data, "items");
blockMappings = loadBiMappings(data, "blocks");
soundMappings = loadMappings(data, "sounds");
}
final CompoundTag tagsTag = data.getCompoundTag("tags");
@@ -109,6 +118,11 @@ public class MappingDataBase implements MappingData {
loadTags(RegistryType.ENTITY, tagsTag);
}
final IntArrayTag changedBlocks = data.getIntArrayTag("changed_blocks");
if (changedBlocks != null) {
this.changedBlocks = new IntOpenHashSet(changedBlocks.getValue());
}
loadExtras(data);
}
@@ -132,6 +146,11 @@ public class MappingDataBase implements MappingData {
return MappingDataLoader.INSTANCE.loadMappings(data, key);
}
protected @Nullable BiMappings loadFullOrBiMappings(final CompoundTag data, final CompoundTag unmappedIdentifiersTag, final CompoundTag mappedIdentifiersTag, final String key) {
final FullMappings mappings = loadFullMappings(data, unmappedIdentifiersTag, mappedIdentifiersTag, key);
return mappings != null ? mappings : loadBiMappings(data, key);
}
protected @Nullable FullMappings loadFullMappings(final CompoundTag data, final CompoundTag unmappedIdentifiersTag, final CompoundTag mappedIdentifiersTag, final String key) {
if (!unmappedIdentifiersTag.contains(key) || !mappedIdentifiersTag.contains(key)) {
return null;
@@ -224,8 +243,8 @@ public class MappingDataBase implements MappingData {
@Override
public @Nullable FullMappings getFullItemMappings() {
if (itemMappings instanceof FullMappings) {
return (FullMappings) itemMappings;
if (itemMappings instanceof FullMappings fullItemMappings) {
return fullItemMappings;
}
return null;
}
@@ -240,6 +259,14 @@ public class MappingDataBase implements MappingData {
return blockMappings;
}
@Override
public @Nullable FullMappings getFullBlockMappings() {
if (blockMappings instanceof FullMappings fullBlockMappings) {
return fullBlockMappings;
}
return null;
}
@Override
public @Nullable FullMappings getBlockEntityMappings() {
return blockEntityMappings;
@@ -255,6 +282,14 @@ public class MappingDataBase implements MappingData {
return soundMappings;
}
@Override
public @Nullable FullMappings getFullSoundMappings() {
if (soundMappings instanceof FullMappings fullSoundMappings) {
return fullSoundMappings;
}
return null;
}
@Override
public @Nullable Mappings getStatisticsMappings() {
return statisticsMappings;
@@ -300,6 +335,11 @@ public class MappingDataBase implements MappingData {
return recipeSerializerMappings;
}
@Override
public @Nullable IntSet changedBlocks() {
return changedBlocks;
}
protected Logger getLogger() {
return Via.getPlatform().getLogger();
}
@@ -210,7 +210,7 @@ public class MappingDataLoader {
return null;
}
final int mappedSize = tag.getIntTag("mappedSize").asInt();
final int mappedSize = tag.getInt("mappedSize", -1);
final byte strategy = tag.getByteTag("id").asByte();
final V mappings;
if (strategy == DIRECT_ID) {
@@ -185,6 +185,20 @@ public interface EntityTracker {
*/
void setCurrentWorld(String currentWorld);
/**
* Returns the id of the current dimension, or -1 if unset (i.e. before 1.20.5).
*
* @return id of the current dimension, or -1 if unset
*/
int currentDimensionId();
/**
* Sets the id of the current dimension.
*
* @param currentDimensionId id of the current dimension
*/
void setCurrentDimensionId(int currentDimensionId);
int biomesSent();
void setBiomesSent(int biomesSent);
@@ -22,7 +22,11 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
/**
* Set of ids that either holds a string tag key or an array of ids.
@@ -32,7 +36,7 @@ public interface HolderSet {
/**
* Creates a new holder set for the given tag.
*
* @param tagKey the tag key
* @param tagKey the tag key, not including '#'
* @return a new holder set
*/
static HolderSet of(final String tagKey) {
@@ -49,10 +53,29 @@ public interface HolderSet {
return new HolderSetImpl.Ids(ids);
}
static HolderSet fromTag(final Tag tag, final Function<String, Integer> mappingFunction) {
if (tag instanceof StringTag stringTag) {
if (stringTag.getValue().startsWith("#")) {
return HolderSet.of(stringTag.getValue().substring(1));
}
final int id = mappingFunction.apply(stringTag.getValue());
return HolderSet.of(new int[]{id});
} else if (tag instanceof ListTag<?> listTag) {
final int[] ids = new int[listTag.size()];
for (int i = 0; i < listTag.size(); i++) {
final String value = ((StringTag) listTag.get(i)).getValue();
ids[i] = mappingFunction.apply(value);
}
return HolderSet.of(ids);
}
throw new IllegalArgumentException();
}
/**
* Gets the tag key.
* Gets the tag key, not including '#'.
*
* @return the tag key
* @return the tag key without a '#'
* @see #hasTagKey()
*/
String tagKey();
@@ -49,6 +49,12 @@ public interface CodecContext {
Key blockEntity(int id);
Key sound(int id);
Key key(MappingData.MappingType mappingType, int id);
int id(MappingData.MappingType mappingType, String identifier);
static RegistryAccess of(final List<String> enchantments, final MappingData mappingData) {
return new RegistryAccessImpl(enchantments, mappingData);
}
@@ -76,6 +76,22 @@ final class RegistryAccessImpl implements CodecContext.RegistryAccess {
return key(mappingData.getBlockEntityMappings(), id);
}
@Override
public Key sound(final int id) {
return key(mappingData.getFullSoundMappings(), id);
}
@Override
public Key key(final MappingData.MappingType mappingType, final int id) {
return key(mappingData.getFullMappings(mappingType), id);
}
@Override
public int id(final MappingData.MappingType mappingType, final String identifier) {
final FullMappings mappings = mappingData.getFullMappings(mappingType);
return mapped ? mappings.mappedId(identifier) : mappings.id(identifier);
}
private Key key(final FullMappings mappings, final int id) {
final String identifier = mapped ? mappings.mappedIdentifier(id) : mappings.identifier(id);
return key(identifier, id);
@@ -27,7 +27,6 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.GameProfile;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
@@ -47,6 +46,7 @@ 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.DebugStickState;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantable;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
@@ -60,10 +60,12 @@ import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.ItemModel;
import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
import com.viaversion.viaversion.api.minecraft.item.data.LockCode;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.Repairable;
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
import com.viaversion.viaversion.api.minecraft.item.data.TooltipDisplay;
@@ -136,7 +138,7 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_2 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_2);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_5 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_5);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_6 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_6);
public static final StructuredDataKey<HolderSet> REPAIRABLE = new StructuredDataKey<>("repairable", Types.HOLDER_SET);
public static final StructuredDataKey<Repairable> REPAIRABLE = new StructuredDataKey<>("repairable", Repairable.TYPE);
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
public static final StructuredDataKey<Key> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.RESOURCE_LOCATION);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
@@ -159,7 +161,7 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
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<ArmorTrim> TRIM1_21_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_5);
public static final StructuredDataKey<CompoundTag> DEBUG_STICK_STATE = new StructuredDataKey<>("debug_stick_state", Types.COMPOUND_TAG);
public static final StructuredDataKey<DebugStickState> DEBUG_STICK_STATE = new StructuredDataKey<>("debug_stick_state", DebugStickState.TYPE);
public static final StructuredDataKey<CompoundTag> ENTITY_DATA1_20_5 = new StructuredDataKey<>("entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<EntityData> ENTITY_DATA1_21_9 = new StructuredDataKey<>("entity_data", EntityData.TYPE);
public static final StructuredDataKey<CompoundTag> BUCKET_ENTITY_DATA = new StructuredDataKey<>("bucket_entity_data", Types.COMPOUND_TAG);
@@ -186,7 +188,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<BlockStateProperties> BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE);
public static final StructuredDataKey<Bee[]> BEES1_20_5 = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE1_20_5);
public static final StructuredDataKey<Bee[]> BEES1_21_9 = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE1_21_9);
public static final StructuredDataKey<Tag> LOCK = new StructuredDataKey<>("lock", Types.TAG);
public static final StructuredDataKey<Tag> LOCK1_20_5 = new StructuredDataKey<>("lock", Types.TAG);
public static final StructuredDataKey<LockCode> LOCK1_21_2 = new StructuredDataKey<>("lock", LockCode.TYPE);
public static final StructuredDataKey<CompoundTag> CONTAINER_LOOT = new StructuredDataKey<>("container_loot", Types.COMPOUND_TAG);
public static final StructuredDataKey<Holder<SoundEvent>> BREAK_SOUND = new StructuredDataKey<>("break_sound", Types.SOUND_EVENT);
@@ -22,8 +22,8 @@
*/
package com.viaversion.viaversion.api.minecraft.entities;
import java.util.HashMap;
import java.util.Map;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class EntityTypes1_10 {
@@ -143,7 +143,7 @@ public class EntityTypes1_10 {
SPIDER(52, ABSTRACT_MONSTER),
CAVE_SPIDER(59, SPIDER);
private static final Map<Integer, EntityType> TYPES = new HashMap<>();
private static final Int2ObjectMap<EntityType> TYPES;
private final int id;
private final EntityType parent;
@@ -184,7 +184,9 @@ public class EntityTypes1_10 {
}
static {
for (EntityType type : EntityType.values()) {
final EntityType[] values = EntityType.values();
TYPES = new Int2ObjectOpenHashMap<>(values.length);
for (EntityType type : values) {
TYPES.put(type.id, type);
}
}
@@ -230,7 +232,7 @@ public class EntityTypes1_10 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private static final Int2ObjectMap<Int2ObjectMap<ObjectType>> TYPES = new Int2ObjectOpenHashMap<>();
private final int id;
private final int data;
@@ -238,7 +240,7 @@ public class EntityTypes1_10 {
static {
for (ObjectType type : ObjectType.values()) {
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
TYPES.computeIfAbsent(type.id, k -> new Int2ObjectOpenHashMap<>()).put(type.data, type);
}
}
@@ -268,7 +270,7 @@ public class EntityTypes1_10 {
}
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
final Int2ObjectMap<ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
@@ -22,8 +22,8 @@
*/
package com.viaversion.viaversion.api.minecraft.entities;
import java.util.HashMap;
import java.util.Map;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class EntityTypes1_11 {
@@ -168,7 +168,7 @@ public class EntityTypes1_11 {
EVOKER(34, ABSTRACT_MONSTER),
VINDICATOR(36, ABSTRACT_MONSTER);
private static final Map<Integer, EntityType> TYPES = new HashMap<>();
private static final Int2ObjectMap<EntityType> TYPES;
private final int id;
private final EntityType parent;
@@ -209,7 +209,9 @@ public class EntityTypes1_11 {
}
static {
for (EntityType type : EntityType.values()) {
final EntityType[] values = EntityType.values();
TYPES = new Int2ObjectOpenHashMap<>(values.length);
for (EntityType type : values) {
TYPES.put(type.id, type);
}
}
@@ -257,7 +259,7 @@ public class EntityTypes1_11 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private static final Int2ObjectMap<Int2ObjectMap<ObjectType>> TYPES = new Int2ObjectOpenHashMap<>();
private final int id;
private final int data;
@@ -265,7 +267,7 @@ public class EntityTypes1_11 {
static {
for (ObjectType type : ObjectType.values()) {
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
TYPES.computeIfAbsent(type.id, k -> new Int2ObjectOpenHashMap<>()).put(type.data, type);
}
}
@@ -295,7 +297,7 @@ public class EntityTypes1_11 {
}
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
final Int2ObjectMap<ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
@@ -22,8 +22,8 @@
*/
package com.viaversion.viaversion.api.minecraft.entities;
import java.util.HashMap;
import java.util.Map;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class EntityTypes1_12 {
@@ -174,7 +174,7 @@ public class EntityTypes1_12 {
EVOKER(34, SPELLCASTER_ILLAGER),
ILLUSIONER(37, SPELLCASTER_ILLAGER);
private static final Map<Integer, EntityType> TYPES = new HashMap<>();
private static final Int2ObjectMap<EntityType> TYPES;
private final int id;
private final EntityType parent;
@@ -215,7 +215,9 @@ public class EntityTypes1_12 {
}
static {
for (EntityType type : EntityType.values()) {
final EntityType[] values = EntityType.values();
TYPES = new Int2ObjectOpenHashMap<>(values.length);
for (EntityType type : values) {
TYPES.put(type.id, type);
}
}
@@ -263,7 +265,7 @@ public class EntityTypes1_12 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private static final Int2ObjectMap<Int2ObjectMap<ObjectType>> TYPES = new Int2ObjectOpenHashMap<>();
private final int id;
private final int data;
@@ -271,7 +273,7 @@ public class EntityTypes1_12 {
static {
for (ObjectType type : ObjectType.values()) {
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
TYPES.computeIfAbsent(type.id, k -> new Int2ObjectOpenHashMap<>()).put(type.data, type);
}
}
@@ -301,7 +303,7 @@ public class EntityTypes1_12 {
}
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
final Int2ObjectMap<ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
@@ -22,8 +22,8 @@
*/
package com.viaversion.viaversion.api.minecraft.entities;
import java.util.HashMap;
import java.util.Map;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class EntityTypes1_13 {
@@ -185,7 +185,7 @@ public class EntityTypes1_13 {
EVOKER(21, SPELLCASTER_ILLAGER),
ILLUSIONER(31, SPELLCASTER_ILLAGER);
private static final Map<Integer, EntityType> TYPES = new HashMap<>();
private static final Int2ObjectMap<EntityType> TYPES;
private final int id;
private final EntityType parent;
@@ -226,7 +226,9 @@ public class EntityTypes1_13 {
}
static {
for (EntityType type : EntityType.values()) {
final EntityType[] values = EntityType.values();
TYPES = new Int2ObjectOpenHashMap<>(values.length);
for (EntityType type : values) {
TYPES.put(type.id, type);
}
}
@@ -275,7 +277,7 @@ public class EntityTypes1_13 {
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL),
TRIDENT(94, EntityType.TRIDENT);
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private static final Int2ObjectMap<Int2ObjectMap<ObjectType>> TYPES = new Int2ObjectOpenHashMap<>();
private final int id;
private final int data;
@@ -283,7 +285,7 @@ public class EntityTypes1_13 {
static {
for (ObjectType type : ObjectType.values()) {
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
TYPES.computeIfAbsent(type.id, k -> new Int2ObjectOpenHashMap<>()).put(type.data, type);
}
}
@@ -313,7 +315,7 @@ public class EntityTypes1_13 {
}
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
final Int2ObjectMap<ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
@@ -22,8 +22,8 @@
*/
package com.viaversion.viaversion.api.minecraft.entities;
import java.util.HashMap;
import java.util.Map;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class EntityTypes1_8 {
@@ -135,7 +135,7 @@ public class EntityTypes1_8 {
SPIDER(52, ABSTRACT_MONSTER),
CAVE_SPIDER(59, SPIDER);
private static final Map<Integer, EntityType> TYPES = new HashMap<>();
private static final Int2ObjectMap<EntityType> TYPES;
private final int id;
private final EntityType parent;
@@ -176,7 +176,9 @@ public class EntityTypes1_8 {
}
static {
for (EntityType type : EntityType.values()) {
final EntityType[] values = EntityType.values();
TYPES = new Int2ObjectOpenHashMap<>(values.length);
for (EntityType type : values) {
TYPES.put(type.id, type);
}
}
@@ -218,7 +220,7 @@ public class EntityTypes1_8 {
ARMOR_STAND(78, EntityType.ARMOR_STAND),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK);
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private static final Int2ObjectMap<Int2ObjectMap<ObjectType>> TYPES = new Int2ObjectOpenHashMap<>();
private final int id;
private final int data;
@@ -226,7 +228,7 @@ public class EntityTypes1_8 {
static {
for (ObjectType type : ObjectType.values()) {
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
TYPES.computeIfAbsent(type.id, k -> new Int2ObjectOpenHashMap<>()).put(type.data, type);
}
}
@@ -256,7 +258,7 @@ public class EntityTypes1_8 {
}
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
final Int2ObjectMap<ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
@@ -22,8 +22,8 @@
*/
package com.viaversion.viaversion.api.minecraft.entities;
import java.util.HashMap;
import java.util.Map;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class EntityTypes1_9 {
@@ -142,7 +142,7 @@ public class EntityTypes1_9 {
SPIDER(52, ABSTRACT_MONSTER),
CAVE_SPIDER(59, SPIDER);
private static final Map<Integer, EntityType> TYPES = new HashMap<>();
private static final Int2ObjectMap<EntityType> TYPES;
private final int id;
private final EntityType parent;
@@ -183,7 +183,9 @@ public class EntityTypes1_9 {
}
static {
for (EntityType type : EntityType.values()) {
final EntityType[] values = EntityType.values();
TYPES = new Int2ObjectOpenHashMap<>(values.length);
for (EntityType type : values) {
TYPES.put(type.id, type);
}
}
@@ -229,7 +231,7 @@ public class EntityTypes1_9 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private static final Int2ObjectMap<Int2ObjectMap<ObjectType>> TYPES = new Int2ObjectOpenHashMap<>();
private final int id;
private final int data;
@@ -237,7 +239,7 @@ public class EntityTypes1_9 {
static {
for (ObjectType type : ObjectType.values()) {
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
TYPES.computeIfAbsent(type.id, k -> new Int2ObjectOpenHashMap<>()).put(type.data, type);
}
}
@@ -267,7 +269,7 @@ public class EntityTypes1_9 {
}
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
final Int2ObjectMap<ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
@@ -59,6 +59,7 @@ public record BlockEntityData(int type, CompoundTag tag) implements Rewritable {
@Override
public BlockEntityData rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final int mappedType = protocol.getMappingData().getBlockEntityMappings().getNewId(type);
return new BlockEntityData(mappedType, tag);
// Empty mappings might be possible for removed block entities, set a dummy value in that case. Will be handled fine by server and client without losing data
return new BlockEntityData(mappedType != -1 ? mappedType : 0, tag);
}
}
@@ -23,24 +23,14 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
public record DamageResistant(Key typesTagKey) {
public static final Type<DamageResistant> TYPE = new Type<>(DamageResistant.class) {
@Override
public DamageResistant read(final ByteBuf buffer) {
final Key typesTagKey = Types.RESOURCE_LOCATION.read(buffer);
return new DamageResistant(typesTagKey);
}
@Override
public void write(final ByteBuf buffer, final DamageResistant value) {
Types.RESOURCE_LOCATION.write(buffer, value.typesTagKey());
}
public static final Type<DamageResistant> TYPE = new TransformingType<>(Types.RESOURCE_LOCATION, DamageResistant.class, DamageResistant::new, DamageResistant::typesTagKey) {
@Override
public void write(final Ops ops, final DamageResistant value) {
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
public record DebugStickState(CompoundTag tag) implements Rewritable, Copyable {
public static final Type<DebugStickState> TYPE = TransformingType.of(Types.COMPOUND_TAG, DebugStickState.class, DebugStickState::new, DebugStickState::tag);
@Override
public DebugStickState rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
CompoundTag updatedTag = tag;
if (clientbound && protocol.getMappingData() != null && protocol.getMappingData().changedBlocks() != null) {
updatedTag = tag.copy();
// Anything beyond this isn't worth the disk space/handling
updatedTag.entrySet().removeIf(entry -> {
final int blockId = protocol.getMappingData().getFullBlockMappings().id(entry.getKey());
return protocol.getMappingData().changedBlocks().contains(blockId);
});
}
return new DebugStickState(updatedTag);
}
@Override
public DebugStickState copy() {
return new DebugStickState(tag.copy());
}
}
@@ -44,6 +44,7 @@ public final class EnumTypes {
public static final EnumType HORSE_VARIANT = new EnumType(Fallback.WRAP, "white", "creamy", "chestnut", "brown", "black", "gray", "dark_brown");
public static final EnumType LLAMA_VARIANT = new EnumType(Fallback.CLAMP, "creamy", "white", "brown", "gray");
public static final EnumType AXOLOTL_VARIANT = new EnumType("lucy", "wild", "gold", "cyan", "blue");
public static final EnumType EQUIPMENT_SLOT = new EnumType("mainhand", "feet", "legs", "chest", "head", "offhand", "body", "saddle");
// Enums with non-ordinal ids
public static final FakeEnumType RABBIT_VARIANT = new FakeEnumType(List.of("brown", "white", "black", "white_splotched", "gold", "salt"), of(99, "evil"));
// Pretty much enums, but with a resource location
@@ -23,12 +23,16 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
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.misc.HolderSetType;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -101,6 +105,21 @@ public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Null
buffer.writeBoolean(value.damageOnHurt());
buffer.writeBoolean(value.equipOnInteract());
}
@Override
public void write(final Ops ops, final Equippable value) {
final Holder<SoundEvent> defaultEquipSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "item.armor.equip_generic"));
ops.writeMap(map -> map
.write("slot", EnumTypes.EQUIPMENT_SLOT, value.equipmentSlot)
.writeOptional("equip_sound", Types.SOUND_EVENT, value.soundEvent, defaultEquipSound)
.writeOptional("asset_id", Types.RESOURCE_LOCATION, value.model != null ? Key.of(value.model) : null)
.writeOptional("camera_overlay", Types.RESOURCE_LOCATION, value.cameraOverlay != null ? Key.of(value.cameraOverlay) : null)
.writeOptional("allowed_entities", new HolderSetType(MappingData.MappingType.ENTITY), value.allowedEntities)
.writeOptional("dispensable", Types.BOOLEAN, value.dispensable, true)
.writeOptional("swappable", Types.BOOLEAN, value.swappable, true)
.writeOptional("damage_on_hurt", Types.BOOLEAN, value.damageOnHurt, true)
.writeOptional("equip_on_interact", Types.BOOLEAN, value.equipOnInteract, false));
}
};
public static final Type<Equippable> TYPE1_21_6 = new Type<>(Equippable.class) {
@Override
@@ -133,6 +152,24 @@ public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Null
buffer.writeBoolean(value.canBeSheared());
Types.SOUND_EVENT.write(buffer, value.shearingSound());
}
@Override
public void write(final Ops ops, final Equippable value) {
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "item.armor.equip_generic"));
final Holder<SoundEvent> defaultShearingSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "item.shears.snip"));
ops.writeMap(map -> map
.write("slot", EnumTypes.EQUIPMENT_SLOT, value.equipmentSlot)
.writeOptional("equip_sound", Types.SOUND_EVENT, value.soundEvent, defaultSound)
.writeOptional("asset_id", Types.RESOURCE_LOCATION, value.model != null ? Key.of(value.model) : null)
.writeOptional("camera_overlay", Types.RESOURCE_LOCATION, value.cameraOverlay != null ? Key.of(value.cameraOverlay) : null)
.writeOptional("allowed_entities", new HolderSetType(MappingData.MappingType.ENTITY), value.allowedEntities)
.writeOptional("dispensable", Types.BOOLEAN, value.dispensable, true)
.writeOptional("swappable", Types.BOOLEAN, value.swappable, true)
.writeOptional("damage_on_hurt", Types.BOOLEAN, value.damageOnHurt, true)
.writeOptional("equip_on_interact", Types.BOOLEAN, value.equipOnInteract, false)
.writeOptional("can_be_sheared", Types.BOOLEAN, value.canBeSheared, false)
.writeOptional("shearing_sound", Types.SOUND_EVENT, value.shearingSound, defaultShearingSound));
}
};
@Override
@@ -23,33 +23,16 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ItemModel(Key key) implements Rewritable {
public static final Type<ItemModel> TYPE = new Type<>(ItemModel.class) {
@Override
public ItemModel read(final ByteBuf buffer) {
final Key key = Types.RESOURCE_LOCATION.read(buffer);
return new ItemModel(key);
}
@Override
public void write(final ByteBuf buffer, final ItemModel value) {
Types.RESOURCE_LOCATION.write(buffer, value.key());
}
@Override
public void write(final Ops ops, final ItemModel data) {
ops.write(Types.RESOURCE_LOCATION, data.key());
}
};
public static final Type<ItemModel> TYPE = TransformingType.of(Types.RESOURCE_LOCATION, ItemModel.class, ItemModel::new, ItemModel::key);
@Override
public ItemModel rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
@@ -0,0 +1,85 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
public record LockCode(CompoundTag tag) implements Rewritable, Copyable {
public static final Type<LockCode> TYPE = TransformingType.of(Types.COMPOUND_TAG, LockCode.class, LockCode::new, LockCode::tag);
@Override
public LockCode rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
CompoundTag updatedTag = tag;
if (clientbound && protocol.getComponentRewriter() != null) {
// Just abuse the component rewriter and keep this one-way
updatedTag = tag.copy();
updatedTag.putString("id", "air");
protocol.getComponentRewriter().handleShowItem(connection, updatedTag);
updatedTag.remove("id");
final FullMappings mappings = protocol.getMappingData().getFullItemMappings();
final Tag itemsTag = updatedTag.get("items");
if (itemsTag != null) {
final HolderSet items = HolderSet.fromTag(itemsTag, key -> mappings.id(key));
items.rewrite(mappings::getNewId);
updatedTag.put("items", toTag(items, mappings));
}
}
return new LockCode(updatedTag);
}
private Tag toTag(final HolderSet holderSet, final FullMappings mappings) {
if (holderSet.hasTagKey()) {
return new StringTag("#" + holderSet.tagKey());
}
final int[] ids = holderSet.ids();
if (ids.length == 1) {
return new StringTag(mappings.mappedIdentifier(ids[0]));
}
final ListTag<StringTag> listTag = new ListTag<>(StringTag.class);
for (final int id : ids) {
listTag.add(new StringTag(mappings.mappedIdentifier(id)));
}
return listTag;
}
@Override
public LockCode copy() {
return new LockCode(tag.copy());
}
}
@@ -0,0 +1,50 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 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.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData.MappingType;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
import com.viaversion.viaversion.util.Rewritable;
public record Repairable(HolderSet items) implements Rewritable {
public static final Type<Repairable> TYPE = new TransformingType<>(Types.HOLDER_SET, Repairable.class, Repairable::new, Repairable::items) {
@Override
public void write(final Ops ops, final Repairable value) {
ops.writeMap(map -> map.write("items", new HolderSetType(MappingType.ITEM), value.items));
}
};
@Override
public Repairable rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final HolderSet items = this.items.rewrite(Rewritable.itemRewriteFunction(protocol, clientbound));
return this.items == items ? this : new Repairable(items);
}
}
@@ -91,7 +91,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_21_5 = register(770, "1.21.5");
public static final ProtocolVersion v1_21_6 = register(771, "1.21.6");
public static final ProtocolVersion v1_21_7 = register(772, "1.21.7-1.21.8", new SubVersionRange("1.21", 7, 8));
public static final ProtocolVersion v1_21_9 = register(773, "1.21.9");
public static final ProtocolVersion v1_21_9 = register(773, "1.21.9-1.21.10", new SubVersionRange("1.21", 9, 10));
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.rewriter;
import com.google.gson.JsonElement;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -34,4 +35,6 @@ public interface ComponentRewriter {
void processText(UserConnection connection, @Nullable JsonElement element);
JsonElement processText(UserConnection connection, @Nullable String json);
void handleShowItem(UserConnection connection, CompoundTag itemTag);
}
@@ -0,0 +1,77 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 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;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import io.netty.buffer.ByteBuf;
import java.util.function.Function;
public class TransformingType<F, T> extends Type<T> {
private final Type<F> from;
private final Function<F, T> mapFunction;
private final Function<T, F> reverseFunction;
protected TransformingType(
final Type<F> from, final Class<T> outputClass,
final Function<F, T> mapFunction, final Function<T, F> reverseFunction
) {
super(from.getTypeName(), outputClass);
this.from = from;
this.mapFunction = mapFunction;
this.reverseFunction = reverseFunction;
}
/**
* Returns a type that transforms the input to a separate output type.
* Useful if you have wrapper classes of a single object.
*
* @param from type to map from
* @param outputClass output class
* @param mapFunction function to map from F to T
* @param reverseFunction function to map from T to F
* @param <F> from type
* @param <T> to type
* @return transforming type
*/
public static <F, T> Type<T> of(
final Type<F> from, final Class<T> outputClass,
final Function<F, T> mapFunction, final Function<T, F> reverseFunction
) {
return new TransformingType<>(from, outputClass, mapFunction, reverseFunction);
}
@Override
public T read(final ByteBuf buffer) {
return mapFunction.apply(from.read(buffer));
}
@Override
public void write(final ByteBuf buffer, final T value) {
from.write(buffer, reverseFunction.apply(value));
}
@Override
public void write(final Ops ops, final T value) {
from.write(ops, reverseFunction.apply(value));
}
}
@@ -22,16 +22,27 @@
*/
package com.viaversion.viaversion.api.type.types.misc;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
public class HolderSetType extends Type<HolderSet> {
private final MappingDataBase.MappingType mappingType;
public HolderSetType() {
this(null);
}
public HolderSetType(final MappingDataBase.MappingType mappingType) {
super(HolderSet.class);
this.mappingType = mappingType;
}
@Override
@@ -63,6 +74,28 @@ public class HolderSetType extends Type<HolderSet> {
}
}
@Override
public void write(final Ops ops, final HolderSet value) {
if (value.hasTagKey()) {
ops.write(Types.TAG_KEY, Key.of(value.tagKey()));
} else {
Preconditions.checkArgument(mappingType != null, "Cannot write HolderSet with direct ids without a mapping type");
if (value.ids().length == 1) {
// Single entries are inlined
final Key key = ops.context().registryAccess().key(mappingType, value.ids()[0]);
ops.write(Types.RESOURCE_LOCATION, key);
return;
}
ops.writeList(list -> {
for (final int id : value.ids()) {
final Key key = ops.context().registryAccess().key(mappingType, id);
list.write(Types.RESOURCE_LOCATION, key);
}
});
}
}
public static final class OptionalHolderSetType extends OptionalType<HolderSet> {
public OptionalHolderSetType() {
@@ -22,16 +22,27 @@
*/
package com.viaversion.viaversion.api.type.types.misc;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class HolderType<T> extends Type<Holder<T>> {
private final MappingData.MappingType mappingType;
protected HolderType() {
this(null);
}
protected HolderType(final MappingData.MappingType mappingType) {
super(Holder.class);
this.mappingType = mappingType;
}
@Override
@@ -57,6 +68,24 @@ public abstract class HolderType<T> extends Type<Holder<T>> {
public abstract void writeDirect(final ByteBuf buffer, final T object);
@Override
public void write(final Ops ops, final Holder<T> value) {
if (value.hasId()) {
ops.write(Types.RESOURCE_LOCATION, identifier(ops, value.id()));
} else {
writeDirect(ops, value.value());
}
}
protected Key identifier(final Ops ops, final int id) {
Preconditions.checkArgument(mappingType != null, "Mapping type is not defined for this HolderType");
return ops.context().registryAccess().key(mappingType, id);
}
public void writeDirect(final Ops ops, final T object) {
throw new UnsupportedOperationException("Write operation not supported for type: " + getTypeName());
}
public abstract static class OptionalHolderType<T> extends HolderType<T> {
private final HolderType<T> type;
@@ -22,12 +22,19 @@
*/
package com.viaversion.viaversion.api.type.types.misc;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
public final class SoundEventType extends HolderType<SoundEvent> {
public SoundEventType() {
super(MappingData.MappingType.SOUND);
}
@Override
public SoundEvent readDirect(final ByteBuf buffer) {
final String resourceLocation = Types.STRING.read(buffer);
@@ -41,6 +48,13 @@ public final class SoundEventType extends HolderType<SoundEvent> {
Types.OPTIONAL_FLOAT.write(buffer, value.fixedRange());
}
@Override
public void writeDirect(final Ops ops, final SoundEvent object) {
ops.writeMap(map -> map
.write("sound_id", Types.RESOURCE_LOCATION, Key.of(object.identifier()))
.writeOptional("range", Types.FLOAT, object.fixedRange()));
}
public static final class OptionalSoundEventType extends OptionalHolderType<SoundEvent> {
public OptionalSoundEventType() {
@@ -124,7 +124,7 @@ public final class Key {
}
public static boolean equals(final String firstIdentifier, final String secondIdentifier) {
return of(firstIdentifier).equals(of(secondIdentifier));
return firstIdentifier != null && secondIdentifier != null && of(firstIdentifier).equals(of(secondIdentifier));
}
public static String namespaced(final String identifier) {
@@ -32,12 +32,11 @@ public record CodecRegistryContext(Protocol<?, ?, ?, ?> protocol, RegistryAccess
private static final Set<StructuredDataKey<?>> NOT_IMPLEMENTED = new ReferenceOpenHashSet<>(List.of(
StructuredDataKey.TRIM1_21_5, StructuredDataKey.TOOL1_21_5, StructuredDataKey.PROVIDES_TRIM_MATERIAL,
StructuredDataKey.CONSUMABLE1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, StructuredDataKey.INSTRUMENT1_21_5,
StructuredDataKey.EQUIPPABLE1_21_5, StructuredDataKey.REPAIRABLE, StructuredDataKey.DEATH_PROTECTION,
StructuredDataKey.BLOCKS_ATTACKS, StructuredDataKey.SUSPICIOUS_STEW_EFFECTS,
StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BREAK_SOUND,
StructuredDataKey.DEATH_PROTECTION, StructuredDataKey.BLOCKS_ATTACKS, StructuredDataKey.SUSPICIOUS_STEW_EFFECTS,
StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.POT_DECORATIONS,
StructuredDataKey.WOLF_VARIANT, StructuredDataKey.WOLF_SOUND_VARIANT, StructuredDataKey.PIG_VARIANT,
StructuredDataKey.COW_VARIANT, StructuredDataKey.CHICKEN_VARIANT, StructuredDataKey.FROG_VARIANT,
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.CAT_VARIANT, StructuredDataKey.EQUIPPABLE1_21_6
StructuredDataKey.PAINTING_VARIANT, StructuredDataKey.CAT_VARIANT
));
public CodecRegistryContext(final Protocol<?, ?, ?, ?> protocol, final RegistryAccess registryAccess, final boolean mapped) {
@@ -34,7 +34,7 @@ public class ConnectionManagerImpl implements ConnectionManager {
protected final Map<UUID, UserConnection> serverConnections = new ConcurrentHashMap<>();
protected final Map<UUID, UserConnection> clientConnections = new ConcurrentHashMap<>();
protected final Set<UserConnection> connections = Collections.newSetFromMap(new ConcurrentHashMap<>());
protected final Set<UserConnection> connections = ConcurrentHashMap.newKeySet();
@Override
public void onLoginSuccess(UserConnection connection) {
@@ -45,7 +45,6 @@ import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.CodecException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
@@ -53,6 +52,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Function;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import org.checkerframework.checker.nullness.qual.Nullable;
public class UserConnectionImpl implements UserConnection {
@@ -60,9 +60,9 @@ public class UserConnectionImpl implements UserConnection {
private static final AtomicLong IDS = new AtomicLong();
private final long id = IDS.incrementAndGet();
private final Map<Class<?>, StorableObject> storedObjects = new ConcurrentHashMap<>();
private final Map<Class<? extends Protocol>, EntityTracker> entityTrackers = new HashMap<>();
private final Map<Class<? extends Protocol>, ItemHasher> itemHashers = new HashMap<>();
private final Map<Class<? extends Protocol>, ClientWorld> clientWorlds = new HashMap<>();
private final Map<Class<? extends Protocol>, EntityTracker> entityTrackers = new Reference2ObjectOpenHashMap<>();
private final Map<Class<? extends Protocol>, ItemHasher> itemHashers = new Reference2ObjectOpenHashMap<>();
private final Map<Class<? extends Protocol>, ClientWorld> clientWorlds = new Reference2ObjectOpenHashMap<>();
private final PacketTracker packetTracker = new PacketTracker(this);
private final Set<UUID> passthroughTokens = Collections.newSetFromMap(CacheBuilder.newBuilder()
.expireAfterWrite(10, TimeUnit.SECONDS)
@@ -41,6 +41,7 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
private int currentWorldSectionHeight = -1;
private int currentMinY;
private String currentWorld;
private int currentDimensionId = -1;
private int biomesSent = -1;
private Map<String, DimensionData> dimensions = Collections.emptyMap();
private boolean instaBuild;
@@ -182,6 +183,16 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
this.currentWorld = currentWorld;
}
@Override
public int currentDimensionId() {
return currentDimensionId;
}
@Override
public void setCurrentDimensionId(final int currentDimensionId) {
this.currentDimensionId = currentDimensionId;
}
@Override
public int biomesSent() {
return biomesSent;
@@ -20,27 +20,28 @@ package com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockFace;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class DoorConnectionHandler implements ConnectionHandler {
private static final Int2ObjectMap<DoorData> DOOR_DATA_MAP = new Int2ObjectOpenHashMap<>();
private static final Map<Short, Integer> CONNECTED_STATES = new HashMap<>();
private static final Int2IntMap CONNECTED_STATES = new Int2IntOpenHashMap();
static ConnectionData.ConnectorInitAction init() {
final List<String> baseDoors = new LinkedList<>();
baseDoors.add("minecraft:oak_door");
baseDoors.add("minecraft:birch_door");
baseDoors.add("minecraft:jungle_door");
baseDoors.add("minecraft:dark_oak_door");
baseDoors.add("minecraft:acacia_door");
baseDoors.add("minecraft:spruce_door");
baseDoors.add("minecraft:iron_door");
final List<String> baseDoors = Arrays.asList(
"minecraft:oak_door",
"minecraft:birch_door",
"minecraft:jungle_door",
"minecraft:dark_oak_door",
"minecraft:acacia_door",
"minecraft:spruce_door",
"minecraft:iron_door"
);
final DoorConnectionHandler connectionHandler = new DoorConnectionHandler();
return blockData -> {
@@ -100,8 +101,7 @@ public class DoorConnectionHandler implements ConnectionHandler {
s |= lowerHalf.facing().ordinal() << 4;
}
Integer newBlockState = CONNECTED_STATES.get(s);
return newBlockState == null ? blockState : newBlockState;
return CONNECTED_STATES.getOrDefault(s, blockState);
}
private record DoorData(boolean lower, boolean rightHinge, boolean powered,
@@ -20,37 +20,38 @@ package com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockFace;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class StairConnectionHandler implements ConnectionHandler {
private static final Int2ObjectMap<StairData> STAIR_DATA_MAP = new Int2ObjectOpenHashMap<>();
private static final Map<Short, Integer> CONNECTED_BLOCKS = new HashMap<>();
private static final Int2IntMap CONNECTED_BLOCKS = new Int2IntOpenHashMap();
static ConnectionData.ConnectorInitAction init() {
final List<String> baseStairs = new LinkedList<>();
baseStairs.add("minecraft:oak_stairs");
baseStairs.add("minecraft:cobblestone_stairs");
baseStairs.add("minecraft:brick_stairs");
baseStairs.add("minecraft:stone_brick_stairs");
baseStairs.add("minecraft:nether_brick_stairs");
baseStairs.add("minecraft:sandstone_stairs");
baseStairs.add("minecraft:spruce_stairs");
baseStairs.add("minecraft:birch_stairs");
baseStairs.add("minecraft:jungle_stairs");
baseStairs.add("minecraft:quartz_stairs");
baseStairs.add("minecraft:acacia_stairs");
baseStairs.add("minecraft:dark_oak_stairs");
baseStairs.add("minecraft:red_sandstone_stairs");
baseStairs.add("minecraft:purpur_stairs");
baseStairs.add("minecraft:prismarine_stairs");
baseStairs.add("minecraft:prismarine_brick_stairs");
baseStairs.add("minecraft:dark_prismarine_stairs");
final List<String> baseStairs = Arrays.asList(
"minecraft:oak_stairs",
"minecraft:cobblestone_stairs",
"minecraft:brick_stairs",
"minecraft:stone_brick_stairs",
"minecraft:nether_brick_stairs",
"minecraft:sandstone_stairs",
"minecraft:spruce_stairs",
"minecraft:birch_stairs",
"minecraft:jungle_stairs",
"minecraft:quartz_stairs",
"minecraft:acacia_stairs",
"minecraft:dark_oak_stairs",
"minecraft:red_sandstone_stairs",
"minecraft:purpur_stairs",
"minecraft:prismarine_stairs",
"minecraft:prismarine_brick_stairs",
"minecraft:dark_prismarine_stairs"
);
final StairConnectionHandler connectionHandler = new StairConnectionHandler();
return blockData -> {
@@ -104,8 +105,7 @@ public class StairConnectionHandler implements ConnectionHandler {
s |= stairData.type() << 4;
s |= stairData.facing().ordinal() << 9;
Integer newBlockState = CONNECTED_BLOCKS.get(s);
return newBlockState == null ? blockState : newBlockState;
return CONNECTED_BLOCKS.getOrDefault(s, blockState);
}
private int getShape(UserConnection user, BlockPosition position, StairData stair) {
@@ -0,0 +1,456 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 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_12_2to1_13.data;
import com.viaversion.viaversion.util.Key;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
public final class ItemIds1_12_2 {
private static final Object2IntMap<String> IDS = new Object2IntOpenHashMap<>();
static {
IDS.put("air", 0);
IDS.put("stone", 1);
IDS.put("grass", 2);
IDS.put("dirt", 3);
IDS.put("cobblestone", 4);
IDS.put("planks", 5);
IDS.put("sapling", 6);
IDS.put("bedrock", 7);
IDS.put("sand", 12);
IDS.put("gravel", 13);
IDS.put("gold_ore", 14);
IDS.put("iron_ore", 15);
IDS.put("coal_ore", 16);
IDS.put("log", 17);
IDS.put("log2", 162);
IDS.put("leaves", 18);
IDS.put("leaves2", 161);
IDS.put("sponge", 19);
IDS.put("glass", 20);
IDS.put("lapis_ore", 21);
IDS.put("lapis_block", 22);
IDS.put("dispenser", 23);
IDS.put("sandstone", 24);
IDS.put("noteblock", 25);
IDS.put("golden_rail", 27);
IDS.put("detector_rail", 28);
IDS.put("sticky_piston", 29);
IDS.put("web", 30);
IDS.put("tallgrass", 31);
IDS.put("deadbush", 32);
IDS.put("piston", 33);
IDS.put("wool", 35);
IDS.put("yellow_flower", 37);
IDS.put("red_flower", 38);
IDS.put("brown_mushroom", 39);
IDS.put("red_mushroom", 40);
IDS.put("gold_block", 41);
IDS.put("iron_block", 42);
IDS.put("stone_slab", 44);
IDS.put("brick_block", 45);
IDS.put("tnt", 46);
IDS.put("bookshelf", 47);
IDS.put("mossy_cobblestone", 48);
IDS.put("obsidian", 49);
IDS.put("torch", 50);
IDS.put("end_rod", 198);
IDS.put("chorus_plant", 199);
IDS.put("chorus_flower", 200);
IDS.put("purpur_block", 201);
IDS.put("purpur_pillar", 202);
IDS.put("purpur_stairs", 203);
IDS.put("purpur_slab", 205);
IDS.put("mob_spawner", 52);
IDS.put("oak_stairs", 53);
IDS.put("chest", 54);
IDS.put("diamond_ore", 56);
IDS.put("diamond_block", 57);
IDS.put("crafting_table", 58);
IDS.put("farmland", 60);
IDS.put("furnace", 61);
IDS.put("ladder", 65);
IDS.put("rail", 66);
IDS.put("stone_stairs", 67);
IDS.put("lever", 69);
IDS.put("stone_pressure_plate", 70);
IDS.put("wooden_pressure_plate", 72);
IDS.put("redstone_ore", 73);
IDS.put("redstone_torch", 76);
IDS.put("stone_button", 77);
IDS.put("snow_layer", 78);
IDS.put("ice", 79);
IDS.put("snow", 80);
IDS.put("cactus", 81);
IDS.put("clay", 82);
IDS.put("jukebox", 84);
IDS.put("fence", 85);
IDS.put("spruce_fence", 188);
IDS.put("birch_fence", 189);
IDS.put("jungle_fence", 190);
IDS.put("dark_oak_fence", 191);
IDS.put("acacia_fence", 192);
IDS.put("pumpkin", 86);
IDS.put("netherrack", 87);
IDS.put("soul_sand", 88);
IDS.put("glowstone", 89);
IDS.put("lit_pumpkin", 91);
IDS.put("trapdoor", 96);
IDS.put("monster_egg", 97);
IDS.put("stonebrick", 98);
IDS.put("brown_mushroom_block", 99);
IDS.put("red_mushroom_block", 100);
IDS.put("iron_bars", 101);
IDS.put("glass_pane", 102);
IDS.put("melon_block", 103);
IDS.put("vine", 106);
IDS.put("fence_gate", 107);
IDS.put("spruce_fence_gate", 183);
IDS.put("birch_fence_gate", 184);
IDS.put("jungle_fence_gate", 185);
IDS.put("dark_oak_fence_gate", 186);
IDS.put("acacia_fence_gate", 187);
IDS.put("brick_stairs", 108);
IDS.put("stone_brick_stairs", 109);
IDS.put("mycelium", 110);
IDS.put("waterlily", 111);
IDS.put("nether_brick", 112);
IDS.put("nether_brick_fence", 113);
IDS.put("nether_brick_stairs", 114);
IDS.put("enchanting_table", 116);
IDS.put("end_portal_frame", 120);
IDS.put("end_stone", 121);
IDS.put("end_bricks", 206);
IDS.put("dragon_egg", 122);
IDS.put("redstone_lamp", 123);
IDS.put("wooden_slab", 126);
IDS.put("sandstone_stairs", 128);
IDS.put("emerald_ore", 129);
IDS.put("ender_chest", 130);
IDS.put("tripwire_hook", 131);
IDS.put("emerald_block", 133);
IDS.put("spruce_stairs", 134);
IDS.put("birch_stairs", 135);
IDS.put("jungle_stairs", 136);
IDS.put("command_block", 137);
IDS.put("beacon", 138);
IDS.put("cobblestone_wall", 139);
IDS.put("wooden_button", 143);
IDS.put("anvil", 145);
IDS.put("trapped_chest", 146);
IDS.put("light_weighted_pressure_plate", 147);
IDS.put("heavy_weighted_pressure_plate", 148);
IDS.put("daylight_detector", 151);
IDS.put("redstone_block", 152);
IDS.put("quartz_ore", 153);
IDS.put("hopper", 154);
IDS.put("quartz_block", 155);
IDS.put("quartz_stairs", 156);
IDS.put("activator_rail", 157);
IDS.put("dropper", 158);
IDS.put("stained_hardened_clay", 159);
IDS.put("barrier", 166);
IDS.put("iron_trapdoor", 167);
IDS.put("hay_block", 170);
IDS.put("carpet", 171);
IDS.put("hardened_clay", 172);
IDS.put("coal_block", 173);
IDS.put("packed_ice", 174);
IDS.put("acacia_stairs", 163);
IDS.put("dark_oak_stairs", 164);
IDS.put("slime", 165);
IDS.put("grass_path", 208);
IDS.put("double_plant", 175);
IDS.put("stained_glass", 95);
IDS.put("stained_glass_pane", 160);
IDS.put("prismarine", 168);
IDS.put("sea_lantern", 169);
IDS.put("red_sandstone", 179);
IDS.put("red_sandstone_stairs", 180);
IDS.put("stone_slab2", 182);
IDS.put("repeating_command_block", 210);
IDS.put("chain_command_block", 211);
IDS.put("magma", 213);
IDS.put("nether_wart_block", 214);
IDS.put("red_nether_brick", 215);
IDS.put("bone_block", 216);
IDS.put("structure_void", 217);
IDS.put("observer", 218);
IDS.put("white_shulker_box", 219);
IDS.put("orange_shulker_box", 220);
IDS.put("magenta_shulker_box", 221);
IDS.put("light_blue_shulker_box", 222);
IDS.put("yellow_shulker_box", 223);
IDS.put("lime_shulker_box", 224);
IDS.put("pink_shulker_box", 225);
IDS.put("gray_shulker_box", 226);
IDS.put("silver_shulker_box", 227);
IDS.put("cyan_shulker_box", 228);
IDS.put("purple_shulker_box", 229);
IDS.put("blue_shulker_box", 230);
IDS.put("brown_shulker_box", 231);
IDS.put("green_shulker_box", 232);
IDS.put("red_shulker_box", 233);
IDS.put("black_shulker_box", 234);
IDS.put("white_glazed_terracotta", 235);
IDS.put("orange_glazed_terracotta", 236);
IDS.put("magenta_glazed_terracotta", 237);
IDS.put("light_blue_glazed_terracotta", 238);
IDS.put("yellow_glazed_terracotta", 239);
IDS.put("lime_glazed_terracotta", 240);
IDS.put("pink_glazed_terracotta", 241);
IDS.put("gray_glazed_terracotta", 242);
IDS.put("silver_glazed_terracotta", 243);
IDS.put("cyan_glazed_terracotta", 244);
IDS.put("purple_glazed_terracotta", 245);
IDS.put("blue_glazed_terracotta", 246);
IDS.put("brown_glazed_terracotta", 247);
IDS.put("green_glazed_terracotta", 248);
IDS.put("red_glazed_terracotta", 249);
IDS.put("black_glazed_terracotta", 250);
IDS.put("concrete", 251);
IDS.put("concrete_powder", 252);
IDS.put("structure_block", 255);
IDS.put("iron_shovel", 256);
IDS.put("iron_pickaxe", 257);
IDS.put("iron_axe", 258);
IDS.put("flint_and_steel", 259);
IDS.put("apple", 260);
IDS.put("bow", 261);
IDS.put("arrow", 262);
IDS.put("coal", 263);
IDS.put("diamond", 264);
IDS.put("iron_ingot", 265);
IDS.put("gold_ingot", 266);
IDS.put("iron_sword", 267);
IDS.put("wooden_sword", 268);
IDS.put("wooden_shovel", 269);
IDS.put("wooden_pickaxe", 270);
IDS.put("wooden_axe", 271);
IDS.put("stone_sword", 272);
IDS.put("stone_shovel", 273);
IDS.put("stone_pickaxe", 274);
IDS.put("stone_axe", 275);
IDS.put("diamond_sword", 276);
IDS.put("diamond_shovel", 277);
IDS.put("diamond_pickaxe", 278);
IDS.put("diamond_axe", 279);
IDS.put("stick", 280);
IDS.put("bowl", 281);
IDS.put("mushroom_stew", 282);
IDS.put("golden_sword", 283);
IDS.put("golden_shovel", 284);
IDS.put("golden_pickaxe", 285);
IDS.put("golden_axe", 286);
IDS.put("string", 287);
IDS.put("feather", 288);
IDS.put("gunpowder", 289);
IDS.put("wooden_hoe", 290);
IDS.put("stone_hoe", 291);
IDS.put("iron_hoe", 292);
IDS.put("diamond_hoe", 293);
IDS.put("golden_hoe", 294);
IDS.put("wheat_seeds", 295);
IDS.put("wheat", 296);
IDS.put("bread", 297);
IDS.put("leather_helmet", 298);
IDS.put("leather_chestplate", 299);
IDS.put("leather_leggings", 300);
IDS.put("leather_boots", 301);
IDS.put("chainmail_helmet", 302);
IDS.put("chainmail_chestplate", 303);
IDS.put("chainmail_leggings", 304);
IDS.put("chainmail_boots", 305);
IDS.put("iron_helmet", 306);
IDS.put("iron_chestplate", 307);
IDS.put("iron_leggings", 308);
IDS.put("iron_boots", 309);
IDS.put("diamond_helmet", 310);
IDS.put("diamond_chestplate", 311);
IDS.put("diamond_leggings", 312);
IDS.put("diamond_boots", 313);
IDS.put("golden_helmet", 314);
IDS.put("golden_chestplate", 315);
IDS.put("golden_leggings", 316);
IDS.put("golden_boots", 317);
IDS.put("flint", 318);
IDS.put("porkchop", 319);
IDS.put("cooked_porkchop", 320);
IDS.put("painting", 321);
IDS.put("golden_apple", 322);
IDS.put("sign", 323);
IDS.put("wooden_door", 324);
IDS.put("bucket", 325);
IDS.put("water_bucket", 326);
IDS.put("lava_bucket", 327);
IDS.put("minecart", 328);
IDS.put("saddle", 329);
IDS.put("iron_door", 330);
IDS.put("redstone", 331);
IDS.put("snowball", 332);
IDS.put("boat", 333);
IDS.put("leather", 334);
IDS.put("milk_bucket", 335);
IDS.put("brick", 336);
IDS.put("clay_ball", 337);
IDS.put("reeds", 338);
IDS.put("paper", 339);
IDS.put("book", 340);
IDS.put("slime_ball", 341);
IDS.put("chest_minecart", 342);
IDS.put("furnace_minecart", 343);
IDS.put("egg", 344);
IDS.put("compass", 345);
IDS.put("fishing_rod", 346);
IDS.put("clock", 347);
IDS.put("glowstone_dust", 348);
IDS.put("fish", 349);
IDS.put("cooked_fish", 350);
IDS.put("dye", 351);
IDS.put("bone", 352);
IDS.put("sugar", 353);
IDS.put("cake", 354);
IDS.put("bed", 355);
IDS.put("repeater", 356);
IDS.put("cookie", 357);
IDS.put("filled_map", 358);
IDS.put("shears", 359);
IDS.put("melon", 360);
IDS.put("pumpkin_seeds", 361);
IDS.put("melon_seeds", 362);
IDS.put("beef", 363);
IDS.put("cooked_beef", 364);
IDS.put("chicken", 365);
IDS.put("cooked_chicken", 366);
IDS.put("rotten_flesh", 367);
IDS.put("ender_pearl", 368);
IDS.put("blaze_rod", 369);
IDS.put("ghast_tear", 370);
IDS.put("gold_nugget", 371);
IDS.put("nether_wart", 372);
IDS.put("potion", 373);
IDS.put("glass_bottle", 374);
IDS.put("spider_eye", 375);
IDS.put("fermented_spider_eye", 376);
IDS.put("blaze_powder", 377);
IDS.put("magma_cream", 378);
IDS.put("brewing_stand", 379);
IDS.put("cauldron", 380);
IDS.put("ender_eye", 381);
IDS.put("speckled_melon", 382);
IDS.put("spawn_egg", 383);
IDS.put("experience_bottle", 384);
IDS.put("fire_charge", 385);
IDS.put("writable_book", 386);
IDS.put("written_book", 387);
IDS.put("emerald", 388);
IDS.put("item_frame", 389);
IDS.put("flower_pot", 390);
IDS.put("carrot", 391);
IDS.put("potato", 392);
IDS.put("baked_potato", 393);
IDS.put("poisonous_potato", 394);
IDS.put("map", 395);
IDS.put("golden_carrot", 396);
IDS.put("skull", 397);
IDS.put("carrot_on_a_stick", 398);
IDS.put("nether_star", 399);
IDS.put("pumpkin_pie", 400);
IDS.put("fireworks", 401);
IDS.put("firework_charge", 402);
IDS.put("enchanted_book", 403);
IDS.put("comparator", 404);
IDS.put("netherbrick", 405);
IDS.put("quartz", 406);
IDS.put("tnt_minecart", 407);
IDS.put("hopper_minecart", 408);
IDS.put("prismarine_shard", 409);
IDS.put("prismarine_crystals", 410);
IDS.put("rabbit", 411);
IDS.put("cooked_rabbit", 412);
IDS.put("rabbit_stew", 413);
IDS.put("rabbit_foot", 414);
IDS.put("rabbit_hide", 415);
IDS.put("armor_stand", 416);
IDS.put("iron_horse_armor", 417);
IDS.put("golden_horse_armor", 418);
IDS.put("diamond_horse_armor", 419);
IDS.put("lead", 420);
IDS.put("name_tag", 421);
IDS.put("command_block_minecart", 422);
IDS.put("mutton", 423);
IDS.put("cooked_mutton", 424);
IDS.put("banner", 425);
IDS.put("end_crystal", 426);
IDS.put("spruce_door", 427);
IDS.put("birch_door", 428);
IDS.put("jungle_door", 429);
IDS.put("acacia_door", 430);
IDS.put("dark_oak_door", 431);
IDS.put("chorus_fruit", 432);
IDS.put("chorus_fruit_popped", 433);
IDS.put("beetroot", 434);
IDS.put("beetroot_seeds", 435);
IDS.put("beetroot_soup", 436);
IDS.put("dragon_breath", 437);
IDS.put("splash_potion", 438);
IDS.put("spectral_arrow", 439);
IDS.put("tipped_arrow", 440);
IDS.put("lingering_potion", 441);
IDS.put("shield", 442);
IDS.put("elytra", 443);
IDS.put("spruce_boat", 444);
IDS.put("birch_boat", 445);
IDS.put("jungle_boat", 446);
IDS.put("acacia_boat", 447);
IDS.put("dark_oak_boat", 448);
IDS.put("totem_of_undying", 449);
IDS.put("shulker_shell", 450);
IDS.put("iron_nugget", 452);
IDS.put("knowledge_book", 453);
IDS.put("record_13", 2256);
IDS.put("record_cat", 2257);
IDS.put("record_blocks", 2258);
IDS.put("record_chirp", 2259);
IDS.put("record_far", 2260);
IDS.put("record_mall", 2261);
IDS.put("record_mellohi", 2262);
IDS.put("record_stal", 2263);
IDS.put("record_strad", 2264);
IDS.put("record_ward", 2265);
IDS.put("record_11", 2266);
IDS.put("record_wait", 2267);
}
public static int getId(final String identifier, final int def) {
int id = IDS.getOrDefault(Key.stripMinecraftNamespace(identifier), -1);
if (id == -1) {
try {
final int parsedId = Integer.parseInt(identifier);
if (IDS.containsValue(parsedId)) {
id = parsedId;
}
} catch (final NumberFormatException ignored) {
}
}
return id != -1 ? id : def;
}
}
@@ -30,6 +30,8 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.data.ItemIds1_12_2;
import com.viaversion.viaversion.protocols.v1_13to1_13_1.Protocol1_13To1_13_1;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.SerializerVersion;
@@ -61,18 +63,25 @@ public class ComponentRewriter1_13<C extends ClientboundPacketType> extends Json
return;
}
final String idTag = tag.getString("id", "");
final CompoundTag itemTag = tag.getCompoundTag("tag");
final NumberTag damageTag = tag.getNumberTag("Damage");
// Call item converter
final int id = ItemIds1_12_2.getId(idTag, 1);
final short damage = damageTag != null ? damageTag.asShort() : 0;
final Item item = new DataItem();
item.setIdentifier(id);
item.setData(damage);
item.setTag(itemTag);
protocol.getItemRewriter().handleItemToClient(null, item);
// Serialize again
if (id != item.identifier()) {
tag.putString("id", Protocol1_13To1_13_1.MAPPINGS.getFullItemMappings().identifier(item.identifier()));
}
if (damage != item.data()) {
tag.put("Damage", new ShortTag(item.data()));
}
@@ -44,11 +44,13 @@ import com.viaversion.viaversion.rewriter.SoundRewriter;
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.ProtocolLogger;
import org.checkerframework.checker.nullness.qual.Nullable;
public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_13, ClientboundPackets1_14, ServerboundPackets1_13, ServerboundPackets1_14> {
public static final MappingData1_14 MAPPINGS = new MappingData1_14();
public static final ProtocolLogger LOGGER = new ProtocolLogger(Protocol1_13_2To1_14.class);
private final EntityPacketRewriter1_14 entityRewriter = new EntityPacketRewriter1_14(this);
private final ItemPacketRewriter1_14 itemRewriter = new ItemPacketRewriter1_14(this);
private final ParticleRewriter<ClientboundPackets1_13> particleRewriter = new ParticleRewriter<>(this);
@@ -134,6 +136,11 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
return MAPPINGS;
}
@Override
public ProtocolLogger getLogger() {
return LOGGER;
}
@Override
public EntityPacketRewriter1_14 getEntityRewriter() {
return entityRewriter;
@@ -17,19 +17,76 @@
*/
package com.viaversion.viaversion.protocols.v1_13_2to1_14.rewriter;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.NumberTag;
import com.viaversion.nbt.tag.ShortTag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.DataItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.rewriter.ComponentRewriter1_13;
import com.viaversion.viaversion.protocols.v1_13_2to1_14.Protocol1_13_2To1_14;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.SerializerVersion;
import com.viaversion.viaversion.util.StringUtil;
import java.util.logging.Level;
public class ComponentRewriter1_14<C extends ClientboundPacketType> extends ComponentRewriter1_13<C> {
public final class ComponentRewriter1_14<C extends ClientboundPacketType> extends JsonNBTComponentRewriter<C> {
public ComponentRewriter1_14(Protocol<C, ?, ?, ?> protocol) {
super(protocol);
public ComponentRewriter1_14(final Protocol<C, ?, ?, ?> protocol) {
super(protocol, ReadType.JSON);
}
@Override
protected void handleTranslate(JsonObject object, String translate) {
// Nothing
protected void handleHoverEvent(UserConnection connection, JsonObject hoverEvent) {
super.handleHoverEvent(connection, hoverEvent);
final String action = hoverEvent.getAsJsonPrimitive("action").getAsString();
if (!action.equals("show_item")) {
return;
}
final JsonElement value = hoverEvent.get("value");
if (value == null) {
return;
}
CompoundTag tag;
try {
tag = ComponentUtil.deserializeLegacyShowItem(value, SerializerVersion.V1_13);
} catch (Exception e) {
if (!Via.getConfig().isSuppressTextComponentConversionWarnings()) {
Protocol1_13_2To1_14.LOGGER.log(Level.WARNING, "Error reading NBT in show_item: " + StringUtil.forLogging(value), e);
}
return;
}
final CompoundTag itemTag = tag.getCompoundTag("tag");
// Call item converter
final Item item = new DataItem();
item.setTag(itemTag);
protocol.getItemRewriter().handleItemToClient(null, item);
// Serialize again
if (itemTag != null) {
tag.put("tag", itemTag);
}
final JsonArray newValue = new JsonArray();
final JsonObject showItem = new JsonObject();
newValue.add(showItem);
try {
showItem.addProperty("text", SerializerVersion.V1_14.toSNBT(tag));
hoverEvent.add("value", newValue);
} catch (Exception e) {
if (!Via.getConfig().isSuppressTextComponentConversionWarnings()) {
Protocol1_13_2To1_14.LOGGER.log(Level.WARNING, "Error writing NBT in show_item: " + StringUtil.forLogging(value), e);
}
}
}
}
@@ -61,7 +61,9 @@ import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
import com.viaversion.viaversion.util.ProtocolLogger;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
@@ -225,18 +227,11 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
});
registerClientbound(ClientboundPackets1_20_3.SET_PLAYER_TEAM, wrapper -> {
final ScoreboardTeamStorage storage = wrapper.user().get(ScoreboardTeamStorage.class);
final String teamName = wrapper.passthrough(Types.STRING);
final byte action = wrapper.passthrough(Types.BYTE);
if (action == 2) {
return;
}
final ScoreboardTeamStorage storage = wrapper.user().get(ScoreboardTeamStorage.class);
if (action == 1) {
storage.removeTeam(teamName);
return;
} else if (action == 0) {
storage.createTeam(teamName);
if (action == 0) {
wrapper.passthrough(Types.TAG); // Display name
wrapper.passthrough(Types.BYTE); // Flags
wrapper.passthrough(Types.STRING); // Name Tag Visibility
@@ -244,28 +239,37 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
wrapper.passthrough(Types.VAR_INT); // Color
wrapper.passthrough(Types.TAG); // Prefix
wrapper.passthrough(Types.TAG); // Suffix
storage.createTeam(teamName);
final String[] players = wrapper.passthrough(Types.STRING_ARRAY);
storage.addPlayerToTeam(teamName, players);
return;
}
final String[] players = wrapper.passthrough(Types.STRING_ARRAY);
if (action == 3) {
} else if (action == 1) {
storage.removeTeam(teamName);
} else if (action == 3) {
final String[] players = wrapper.passthrough(Types.STRING_ARRAY);
storage.addPlayerToTeam(teamName, players);
} else if (action != 4) {
}
if (action != 4) {
return;
}
final String[] players = wrapper.read(Types.STRING_ARRAY);
// Drop invalid remove packets to not break when plugins do that, since strict error handling is enforced in newer protocols.
final Set<String> filteredPlayers = new HashSet<>();
for (final String player : players) {
final String team = storage.getPlayerTeam(player);
if (!Objects.equals(team, teamName)) {
wrapper.cancel();
return;
break;
}
storage.removeFromTeam(teamName, player);
filteredPlayers.add(player);
}
if (!filteredPlayers.isEmpty()) {
wrapper.write(Types.STRING_ARRAY, filteredPlayers.toArray(new String[0]));
} else {
wrapper.cancel();
}
});
@@ -330,7 +334,7 @@ public final class Protocol1_20_3To1_20_5 extends AbstractProtocol<ClientboundPa
.add(StructuredDataKey.FIREWORKS).add(StructuredDataKey.PROFILE1_20_5).add(StructuredDataKey.NOTE_BLOCK_SOUND)
.add(StructuredDataKey.BANNER_PATTERNS).add(StructuredDataKey.BASE_COLOR).add(StructuredDataKey.POT_DECORATIONS)
.add(StructuredDataKey.BLOCK_STATE).add(StructuredDataKey.BEES1_20_5)
.add(StructuredDataKey.LOCK).add(StructuredDataKey.CONTAINER_LOOT).add(StructuredDataKey.TOOL1_20_5)
.add(StructuredDataKey.LOCK1_20_5).add(StructuredDataKey.CONTAINER_LOOT).add(StructuredDataKey.TOOL1_20_5)
.add(StructuredDataKey.ITEM_NAME).add(StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER)
.add(VersionedTypes.V1_20_5.structuredDataKeys().keys());
@@ -21,6 +21,7 @@ import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.data.MappingDataBase;
import com.viaversion.viaversion.api.data.MappingDataLoader;
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.Protocol1_20_3To1_20_5;
import com.viaversion.viaversion.util.KeyMappings;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
@@ -30,8 +31,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class MappingData1_20_5 extends MappingDataBase {
private final Object2ObjectMap<String, CompoundTag> damageTypes = new Object2ObjectOpenHashMap<>();
private KeyMappings blocks;
private KeyMappings sounds;
public MappingData1_20_5() {
super("1.20.3", "1.20.5");
@@ -41,10 +40,6 @@ public class MappingData1_20_5 extends MappingDataBase {
protected void loadExtras(final CompoundTag data) {
super.loadExtras(data);
final CompoundTag extraMappings = MappingDataLoader.INSTANCE.loadNBT("extra-identifiers-1.20.3.nbt");
blocks = new KeyMappings(extraMappings.getListTag("blocks", StringTag.class));
sounds = new KeyMappings(extraMappings.getListTag("sounds", StringTag.class));
final CompoundTag damageTypes = MappingDataLoader.INSTANCE.loadNBT("damage-types-1.20.3.nbt");
for (final String key : damageTypes.keySet()) {
this.damageTypes.put(key, damageTypes.getCompoundTag(key));
@@ -52,19 +47,19 @@ public class MappingData1_20_5 extends MappingDataBase {
}
public int blockId(final String name) {
return blocks.keyToId(name);
return Protocol1_20_3To1_20_5.MAPPINGS.getFullBlockMappings().id(name);
}
public @Nullable String blockName(final int id) {
return blocks.idToKey(id);
return Protocol1_20_3To1_20_5.MAPPINGS.getFullBlockMappings().identifier(id);
}
public int soundId(final String name) {
return sounds.keyToId(name);
return Protocol1_20_3To1_20_5.MAPPINGS.getFullSoundMappings().id(name);
}
public @Nullable String soundName(final int id) {
return sounds.idToKey(id);
return Protocol1_20_3To1_20_5.MAPPINGS.getFullSoundMappings().identifier(id);
}
public CompoundTag damageType(final String key) {
@@ -54,6 +54,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.BlockPredicate;
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
import com.viaversion.viaversion.api.minecraft.item.data.DebugStickState;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.data.FilterableComponent;
@@ -508,7 +509,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
final CompoundTag debugProperty = tag.getCompoundTag("DebugProperty");
if (debugProperty != null) {
data.set(StructuredDataKey.DEBUG_STICK_STATE, debugProperty.copy());
data.set(StructuredDataKey.DEBUG_STICK_STATE, new DebugStickState(debugProperty.copy()));
}
final NumberTag unbreakable = tag.getNumberTag("Unbreakable");
@@ -1448,7 +1449,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
if (data != null) {
final StringTag lockTag = tag.getStringTag("Lock");
if (lockTag != null) {
data.set(StructuredDataKey.LOCK, lockTag);
data.set(StructuredDataKey.LOCK1_20_5, lockTag);
}
final ListTag<CompoundTag> beesTag = tag.getListTag("Bees", CompoundTag.class);
@@ -52,6 +52,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.BlockPredicate;
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
import com.viaversion.viaversion.api.minecraft.item.data.DebugStickState;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.data.FilterableComponent;
@@ -155,7 +156,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
register(StructuredDataKey.WRITABLE_BOOK_CONTENT, this::writableBookContentToTag, this::writableBookContentFromTag);
register(StructuredDataKey.WRITTEN_BOOK_CONTENT, this::writtenBookContentToTag, this::writtenBookContentFromTag);
register(StructuredDataKey.TRIM1_20_5, this::trimToTag, this::trimFromTag);
register(StructuredDataKey.DEBUG_STICK_STATE, this::debugStickRateToTag, this::debugStickRateFromTag);
register(StructuredDataKey.DEBUG_STICK_STATE, this::debugStickStateToTag, this::debugStickStateFromTag);
register(StructuredDataKey.ENTITY_DATA1_20_5, this::entityDataToTag, this::entityDataFromTag);
register(StructuredDataKey.BUCKET_ENTITY_DATA, this::bucketEntityDataToTag, this::bucketEntityDataFromTag);
register(StructuredDataKey.BLOCK_ENTITY_DATA1_20_5, this::blockEntityDataToTag, this::blockEntityDataFromTag);
@@ -173,7 +174,7 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
register(StructuredDataKey.V1_20_5.container, this::containerToTag, this::containerFromTag);
register(StructuredDataKey.BLOCK_STATE, this::blockStateToTag, this::blockStateFromTag);
register(StructuredDataKey.BEES1_20_5, this::beesToTag, this::beesFromTag);
register(StructuredDataKey.LOCK, this::lockToTag, this::lockFromTag);
register(StructuredDataKey.LOCK1_20_5, this::lockToTag, this::lockFromTag);
register(StructuredDataKey.CONTAINER_LOOT, this::containerLootToTag, this::containerLootFromTag);
}
@@ -1058,12 +1059,12 @@ public class ComponentRewriter1_20_5<C extends ClientboundPacketType> extends Js
return new ArmorTrim(material, pattern, showInTooltip);
}
protected CompoundTag debugStickRateToTag(final CompoundTag value) {
return value;
protected CompoundTag debugStickStateToTag(final DebugStickState value) {
return value.tag();
}
protected CompoundTag debugStickRateFromTag(final Tag value) {
return (CompoundTag) value;
protected DebugStickState debugStickStateFromTag(final Tag value) {
return new DebugStickState((CompoundTag) value);
}
protected CompoundTag entityDataToTag(final CompoundTag value) {
@@ -318,7 +318,7 @@ public final class StructuredDataConverter {
}
getBlockEntityTag(tag, "beehive").put("Bees", bees);
});
register(StructuredDataKey.LOCK, (data, tag) -> getBlockEntityTag(tag).put("Lock", data));
register(StructuredDataKey.LOCK1_20_5, (data, tag) -> getBlockEntityTag(tag).put("Lock", data));
register(StructuredDataKey.NOTE_BLOCK_SOUND, (data, tag) -> getBlockEntityTag(tag, "player_head").putString("note_block_sound", data.original()));
register(StructuredDataKey.POT_DECORATIONS, (data, tag) -> {
IntArrayTag originalSherds = null;
@@ -341,7 +341,7 @@ public final class StructuredDataConverter {
}
getBlockEntityTag(tag, "decorated_pot").put("sherds", sherds);
});
register(StructuredDataKey.DEBUG_STICK_STATE, (data, tag) -> tag.put("DebugProperty", data));
register(StructuredDataKey.DEBUG_STICK_STATE, (data, tag) -> tag.put("DebugProperty", data.tag()));
register(StructuredDataKey.RECIPES, (data, tag) -> tag.put("Recipes", data));
register(StructuredDataKey.ENTITY_DATA1_20_5, (data, tag) -> tag.put("EntityTag", data));
register(StructuredDataKey.BUCKET_ENTITY_DATA, (data, tag) -> {
@@ -41,7 +41,16 @@ public final class ScoreboardTeamStorage implements StorableObject {
}
public void addPlayerToTeam(final String team, final String[] player) {
final Set<String> players = this.teams.computeIfAbsent(team, k -> new HashSet<>());
final Set<String> players = this.teams.get(team);
if (players == null) {
return;
}
for (final Set<String> allPlayers : this.teams.values()) {
for (final String toRemove : player) {
allPlayers.remove(toRemove);
}
}
Collections.addAll(players, player);
}
@@ -217,7 +217,7 @@ public final class Protocol1_20_5To1_21 extends AbstractProtocol<ClientboundPack
.add(StructuredDataKey.FIREWORKS).add(StructuredDataKey.PROFILE1_20_5).add(StructuredDataKey.NOTE_BLOCK_SOUND)
.add(StructuredDataKey.BANNER_PATTERNS).add(StructuredDataKey.BASE_COLOR).add(StructuredDataKey.POT_DECORATIONS)
.add(StructuredDataKey.BLOCK_STATE).add(StructuredDataKey.BEES1_20_5)
.add(StructuredDataKey.LOCK).add(StructuredDataKey.CONTAINER_LOOT).add(StructuredDataKey.TOOL1_20_5)
.add(StructuredDataKey.LOCK1_20_5).add(StructuredDataKey.CONTAINER_LOOT).add(StructuredDataKey.TOOL1_20_5)
.add(StructuredDataKey.ITEM_NAME).add(StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER)
.add(StructuredDataKey.FOOD1_21).add(StructuredDataKey.JUKEBOX_PLAYABLE1_21).add(StructuredDataKey.ATTRIBUTE_MODIFIERS1_21);
@@ -18,6 +18,8 @@
package com.viaversion.viaversion.protocols.v1_20_5to1_21.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
@@ -37,8 +39,10 @@ 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.PlayerPositionStorage;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.WolfVariantRegistryMarker;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.util.Key;
public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPacket1_20_5, Protocol1_20_5To1_21> {
@@ -58,7 +62,15 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
campfireDamageType.putString("message_id", "inFire");
campfireDamageType.putFloat("exhaustion", 0.1F);
registryDataRewriter.addEntries("damage_type", new RegistryEntry("minecraft:campfire", campfireDamageType));
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, registryDataRewriter::handle);
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, wrapper -> {
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
RegistryEntry[] entries = wrapper.read(Types.REGISTRY_ENTRY_ARRAY);
entries = registryDataRewriter.handle(wrapper.user(), registryKey, entries);
wrapper.write(Types.REGISTRY_ENTRY_ARRAY, entries);
if (registryKey.equals("wolf_variant")) {
wrapper.user().put(new WolfVariantRegistryMarker());
}
});
protocol.registerFinishConfiguration(ClientboundConfigurationPackets1_20_5.FINISH_CONFIGURATION, wrapper -> {
// Add new registries
@@ -91,6 +103,10 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
jukeboxSongsPacket.write(Types.STRING, "minecraft:jukebox_song");
jukeboxSongsPacket.write(Types.REGISTRY_ENTRY_ARRAY, protocol.getMappingData().jukeboxSongs());
jukeboxSongsPacket.send(Protocol1_20_5To1_21.class);
if (!wrapper.user().has(WolfVariantRegistryMarker.class)) {
createDefaultWolfVariantRegistryDataPacket(wrapper).send(Protocol1_20_5To1_21.class);
}
});
registerLogin1_20_5(ClientboundPackets1_20_5.LOGIN);
@@ -138,6 +154,24 @@ public final class EntityPacketRewriter1_21 extends EntityRewriter<ClientboundPa
});
}
private static PacketWrapper createDefaultWolfVariantRegistryDataPacket(final PacketWrapper wrapper) {
final PacketWrapper wolfVariantPacket = wrapper.create(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA);
wolfVariantPacket.write(Types.STRING, "minecraft:wolf_variant");
wolfVariantPacket.write(Types.REGISTRY_ENTRY_ARRAY, getDefaultWolfVariantRegistryEntries());
return wolfVariantPacket;
}
private static RegistryEntry[] getDefaultWolfVariantRegistryEntries() {
final CompoundTag paleWolfVariant = new CompoundTag();
paleWolfVariant.putString("wild_texture", "minecraft:entity/wolf/wolf");
paleWolfVariant.putString("angry_texture", "minecraft:entity/wolf/wolf_angry");
paleWolfVariant.put("biomes", new ListTag<>(StringTag.class));
paleWolfVariant.putString("tame_texture", "minecraft:entity/wolf/wolf_tame");
return new RegistryEntry[]{
new RegistryEntry("minecraft:pale", paleWolfVariant),
};
}
private void storePosition(final PacketWrapper wrapper) {
final double x = wrapper.passthrough(Types.DOUBLE);
final double y = wrapper.passthrough(Types.DOUBLE);
@@ -0,0 +1,23 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.viaversion.viaversion.protocols.v1_20_5to1_21.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
public final class WolfVariantRegistryMarker implements StorableObject {
}
@@ -177,7 +177,7 @@ public final class Protocol1_21_2To1_21_4 extends AbstractProtocol<ClientboundPa
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA1_20_5, StructuredDataKey.INSTRUMENT1_21_2,
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
StructuredDataKey.PROFILE1_20_5, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_20_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
@@ -189,7 +189,7 @@ public final class Protocol1_21_4To1_21_5 extends AbstractProtocol<ClientboundPa
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA1_20_5, StructuredDataKey.INSTRUMENT1_21_5,
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
StructuredDataKey.PROFILE1_20_5, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_21_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_5,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
@@ -153,7 +153,7 @@ public final class Protocol1_21_5To1_21_6 extends AbstractProtocol<ClientboundPa
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA1_20_5, StructuredDataKey.INSTRUMENT1_21_5,
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
StructuredDataKey.PROFILE1_20_5, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_21_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_6,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
@@ -49,6 +49,7 @@ import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter.BlockItemPac
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter.ComponentRewriter1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter.EntityPacketRewriter1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter.ParticleRewriter1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.storage.DimensionScaleStorage;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.storage.LastExplosionPowerStorage;
import com.viaversion.viaversion.rewriter.AttributeRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
@@ -121,6 +122,18 @@ public final class Protocol1_21_7To1_21_9 extends AbstractProtocol<ClientboundPa
wrapper.write(Types.VAR_INT, 0); // Number of block particles
});
registerServerbound(ServerboundPackets1_21_6.DEBUG_SAMPLE_SUBSCRIPTION, wrapper -> {
final int count = wrapper.read(Types.VAR_INT); // subscription count
for (int i = 0; i < count; i++) {
final int id = wrapper.read(Types.VAR_INT); // subscription registry id
if (id == 0) { // DEDICATED_SERVER_TICK_TIME
wrapper.clearPacket();
wrapper.write(Types.VAR_INT, 0); // debug sample type (TICK_TIME)
return;
}
}
wrapper.cancel();
});
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_6.SOUND);
soundRewriter.registerSound1_19_3(ClientboundPackets1_21_6.SOUND_ENTITY);
@@ -129,7 +142,6 @@ public final class Protocol1_21_7To1_21_9 extends AbstractProtocol<ClientboundPa
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21_6.UPDATE_ATTRIBUTES);
cancelServerbound(ServerboundConfigurationPackets1_21_9.ACCEPT_CODE_OF_CONDUCT);
cancelServerbound(ServerboundPackets1_21_6.DEBUG_SAMPLE_SUBSCRIPTION);
}
@Override
@@ -166,7 +178,7 @@ public final class Protocol1_21_7To1_21_9 extends AbstractProtocol<ClientboundPa
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA1_21_9, StructuredDataKey.INSTRUMENT1_21_5,
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
StructuredDataKey.PROFILE1_21_9, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_21_9, StructuredDataKey.LOCK,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_21_9, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_21_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21_5, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21_6,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
@@ -186,6 +198,7 @@ public final class Protocol1_21_7To1_21_9 extends AbstractProtocol<ClientboundPa
public void init(final UserConnection connection) {
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_9.PLAYER));
addItemHasher(connection, new ItemHasherBase(this, connection));
connection.put(new DimensionScaleStorage());
}
@Override
@@ -18,6 +18,7 @@
package com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
@@ -26,6 +27,8 @@ import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
import com.viaversion.viaversion.api.minecraft.item.data.BlockEntityData;
import com.viaversion.viaversion.api.minecraft.item.data.EntityData;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_21_5;
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.RecipeDisplayRewriter1_21_5;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
@@ -33,6 +36,7 @@ import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.Protocol1_21_7To1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.storage.DimensionScaleStorage;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
@@ -68,6 +72,9 @@ public final class BlockItemPacketRewriter1_21_9 extends StructuredItemRewriter<
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21_6.UPDATE_RECIPES);
recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21_6.RECIPE_BOOK_ADD);
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21_6.PLACE_GHOST_RECIPE);
protocol.registerClientbound(ClientboundPackets1_21_6.INITIALIZE_BORDER, this::updateBorderCenter);
protocol.registerClientbound(ClientboundPackets1_21_6.SET_BORDER_CENTER, this::updateBorderCenter);
}
@Override
@@ -116,4 +123,19 @@ public final class BlockItemPacketRewriter1_21_9 extends StructuredItemRewriter<
});
container.replace(StructuredDataKey.PROFILE1_21_9, StructuredDataKey.PROFILE1_20_5, ResolvableProfile::profile);
}
private void updateBorderCenter(final PacketWrapper wrapper) {
double centerX = wrapper.read(Types.DOUBLE);
double centerZ = wrapper.read(Types.DOUBLE);
final EntityTracker tracker = protocol.getEntityRewriter().tracker(wrapper.user());
if (tracker.currentDimensionId() != -1) {
final double scale = wrapper.user().get(DimensionScaleStorage.class).getScale(tracker.currentDimensionId());
centerX /= scale;
centerZ /= scale;
}
wrapper.write(Types.DOUBLE, centerX);
wrapper.write(Types.DOUBLE, centerZ);
}
}
@@ -18,8 +18,10 @@
package com.viaversion.viaversion.protocols.v1_21_7to1_21_9.rewriter;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.GlobalBlockPosition;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_9;
@@ -31,6 +33,7 @@ import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundCon
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPacket1_21_6;
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.Protocol1_21_7To1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.storage.DimensionScaleStorage;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
import com.viaversion.viaversion.rewriter.entitydata.EntityDataHandler;
@@ -94,7 +97,36 @@ public final class EntityPacketRewriter1_21_9 extends EntityRewriter<Clientbound
wrapper.write(Types.FLOAT, 0F); // Pitch
});
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol);
final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(protocol) {
@Override
protected void handleParticleData(final CompoundTag particleData) {
final String type = particleData.getString("type");
if (type != null && Key.stripMinecraftNamespace(type).equals("flash")) {
particleData.putInt("color", -1);
}
super.handleParticleData(particleData);
}
@Override
public void trackDimensionAndBiomes(final UserConnection connection, final String registryKey, final RegistryEntry[] entries) {
super.trackDimensionAndBiomes(connection, registryKey, entries);
if (!registryKey.equals("dimension_type")) {
return;
}
final DimensionScaleStorage dimensionScaleStorage = connection.get(DimensionScaleStorage.class);
for (int i = 0; i < entries.length; i++) {
final RegistryEntry entry = entries[i];
final CompoundTag dimension = (CompoundTag) entry.tag();
if (dimension == null) {
continue;
}
final double coordinateScale = dimension.getDouble("coordinate_scale", 1);
dimensionScaleStorage.setScale(i, coordinateScale);
}
}
};
registryDataRewriter.addHandler("dimension_type", (key, dimension) -> {
if (Key.equals(key, "minecraft:the_end")) {
dimension.putFloat("ambient_light", 0.25F); // End now has actual skylight
@@ -0,0 +1,35 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 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_7to1_21_9.storage;
import com.viaversion.viaversion.api.connection.StorableObject;
import java.util.HashMap;
import java.util.Map;
public final class DimensionScaleStorage implements StorableObject {
private final Map<Integer, Double> dimensionScales = new HashMap<>(4);
public double getScale(final int dimensionId) {
return dimensionScales.getOrDefault(dimensionId, 1D);
}
public void setScale(final int dimensionId, final double scale) {
dimensionScales.put(dimensionId, scale);
}
}
@@ -263,7 +263,7 @@ public final class Protocol1_21To1_21_2 extends AbstractProtocol<ClientboundPack
StructuredDataKey.BUCKET_ENTITY_DATA, StructuredDataKey.BLOCK_ENTITY_DATA1_20_5, StructuredDataKey.INSTRUMENT1_21_2,
StructuredDataKey.RECIPES, StructuredDataKey.LODESTONE_TRACKER, StructuredDataKey.FIREWORK_EXPLOSION, StructuredDataKey.FIREWORKS,
StructuredDataKey.PROFILE1_20_5, StructuredDataKey.NOTE_BLOCK_SOUND, StructuredDataKey.BANNER_PATTERNS, StructuredDataKey.BASE_COLOR,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK,
StructuredDataKey.POT_DECORATIONS, StructuredDataKey.BLOCK_STATE, StructuredDataKey.BEES1_20_5, StructuredDataKey.LOCK1_21_2,
StructuredDataKey.CONTAINER_LOOT, StructuredDataKey.TOOL1_20_5, StructuredDataKey.ITEM_NAME, StructuredDataKey.OMINOUS_BOTTLE_AMPLIFIER,
StructuredDataKey.FOOD1_21_2, StructuredDataKey.JUKEBOX_PLAYABLE1_21, StructuredDataKey.ATTRIBUTE_MODIFIERS1_21,
StructuredDataKey.REPAIRABLE, StructuredDataKey.ENCHANTABLE, StructuredDataKey.CONSUMABLE1_21_2,
@@ -45,6 +45,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.LockCode;
import com.viaversion.viaversion.api.minecraft.item.data.PotionEffect;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Types;
@@ -569,14 +570,14 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
});
dataContainer.replaceKey(StructuredDataKey.POTION_CONTENTS1_20_5, StructuredDataKey.POTION_CONTENTS1_21_2);
dataContainer.replace(StructuredDataKey.FIRE_RESISTANT, StructuredDataKey.DAMAGE_RESISTANT, fireResistant -> new DamageResistant(Key.of("minecraft:is_fire")));
dataContainer.replace(StructuredDataKey.LOCK, tag -> {
dataContainer.replace(StructuredDataKey.LOCK1_20_5, StructuredDataKey.LOCK1_21_2, tag -> {
final String lock = ((StringTag) tag).getValue();
final CompoundTag predicateTag = new CompoundTag();
final CompoundTag itemComponentsTag = new CompoundTag();
predicateTag.put("components", itemComponentsTag);
// As json here...
itemComponentsTag.putString("custom_name", ComponentUtil.plainToJson(lock).toString());
return predicateTag;
return new LockCode(predicateTag);
});
dataContainer.replace(StructuredDataKey.TRIM1_20_5, StructuredDataKey.TRIM1_21_2, trim -> {
// TODO Rewrite from int to string id via sent registry
@@ -589,8 +590,8 @@ public final class BlockItemPacketRewriter1_21_2 extends StructuredItemRewriter<
public static void downgradeItemData(final Item item) {
final StructuredDataContainer dataContainer = item.dataContainer();
dataContainer.replace(StructuredDataKey.LOCK, StructuredDataKey.LOCK, lock -> {
final CompoundTag predicateTag = (CompoundTag) lock;
dataContainer.replace(StructuredDataKey.LOCK1_21_2, StructuredDataKey.LOCK1_20_5, lock -> {
final CompoundTag predicateTag = lock.tag();
final CompoundTag itemComponentsTag = predicateTag.getCompoundTag("components");
if (itemComponentsTag == null) {
return null;
@@ -71,7 +71,7 @@ public final class ComponentRewriter1_21_2 extends JsonNBTComponentRewriter<Clie
levels.entrySet().removeIf(entry -> ((NumberTag) entry.getValue()).asInt() == 0);
}
removeDataComponents(componentsTag, StructuredDataKey.FIRE_RESISTANT, StructuredDataKey.LOCK);
removeDataComponents(componentsTag, StructuredDataKey.FIRE_RESISTANT, StructuredDataKey.LOCK1_20_5);
final StringTag customName = TagUtil.getNamespacedStringTag(componentsTag, "custom_name");
final StringTag itemName = TagUtil.getNamespacedStringTag(componentsTag, "item_name");
@@ -536,6 +536,7 @@ public abstract class EntityRewriter<C extends ClientboundPacketType, T extends
dimensionData = tracker.dimensionData("overworld");
Preconditions.checkNotNull(dimensionData, "Overworld data missing");
}
tracker.setCurrentDimensionId(dimensionId);
tracker.setCurrentWorldSectionHeight(dimensionData.height() >> 4);
tracker.setCurrentMinY(dimensionData.minY());
trackWorld(connection, world);
@@ -74,6 +74,8 @@ public class RegistryDataRewriter {
updateTrimMaterials(entries);
} else if (key.equals("jukebox_song")) {
updateJukeboxSongs(entries);
} else if (key.equals("worldgen/biome")) {
updateBiomes(entries);
}
final BiConsumer<String, CompoundTag> registryEntryHandler = this.registryEntryHandlers.get(key);
@@ -219,6 +221,24 @@ public class RegistryDataRewriter {
// can be overridden
}
public void updateBiomes(final RegistryEntry[] entries) {
for (final RegistryEntry entry : entries) {
if (entry.tag() == null) {
continue;
}
final CompoundTag effects = ((CompoundTag) entry.tag()).getCompoundTag("effects");
if (effects == null) {
continue;
}
final CompoundTag particle = effects.getCompoundTag("particle");
if (particle != null) {
handleParticleData(particle.getCompoundTag("options"));
}
}
}
private void updateNestedEffect(final CompoundTag effectsTag) {
final CompoundTag effect = effectsTag.getCompoundTag("effect");
if (effect == null) {
@@ -248,11 +268,8 @@ public class RegistryDataRewriter {
}
}
private void updateParticleField(final CompoundTag effectTag) {
final CompoundTag particleData = effectTag.getCompoundTag("particle");
if (particleData != null) {
updateType(particleData, "type", protocol.getMappingData().getParticleMappings());
}
protected void handleParticleData(final CompoundTag particleData) {
updateType(particleData, "type", protocol.getMappingData().getParticleMappings());
}
private void runEffectRewriters(final CompoundTag effectTag) {
@@ -265,7 +282,10 @@ public class RegistryDataRewriter {
if (effect.equals("attribute")) {
updateType(effectTag, "attribute", protocol.getMappingData().getAttributeMappings());
} else if (effect.equals("spawn_particles")) {
updateParticleField(effectTag);
final CompoundTag particleData = effectTag.getCompoundTag("particle");
if (particleData != null) {
handleParticleData(particleData);
}
}
final Consumer<CompoundTag> rewriter = enchantmentEffectHandlers.get(effect);
@@ -285,7 +285,8 @@ public abstract class ComponentRewriterBase<C extends ClientboundPacketType> imp
protected abstract void handleHoverEvent(final UserConnection connection, final CompoundTag hoverEventTag);
protected final void handleShowItem(final UserConnection connection, final CompoundTag itemTag) {
@Override
public final void handleShowItem(final UserConnection connection, final CompoundTag itemTag) {
handleShowItem(connection, itemTag, itemTag.getCompoundTag("components"));
}
@@ -309,6 +310,8 @@ public abstract class ComponentRewriterBase<C extends ClientboundPacketType> imp
if (useRemainder != null) {
handleShowItem(connection, useRemainder);
}
removeDataComponents(componentsTag, "lock", "debug_stick_state");
}
protected void handleAttributeModifiers(final CompoundTag tag) {
Loaded 100 of 108 files, more files were not shown because too many files have changed in this diff. Show more