Compare commits

...
Author SHA1 Message Date
Florian Reuth 4be33cbe2c Fix FilterableComponent hashing
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-29 10:34:12 +02:00
Florian Reuth e813796d9a Handle remaining components in registry data (#5077) 2026-09-28 19:31:54 +02:00
Florian Reuth 271b6e7ff7 Fix splash potion sounds not playing in 26.2->26.3 (#5076) 2026-09-28 19:30:57 +02:00
LeonTG 7bf4a30075 Fix ender dragon having the wrong dragon phase in 1.8->1.9 (#5070) 2026-09-28 08:55:09 +02:00
PolangandFlorian Reuth 414e978829 Skip removal markers in 1.20.5+ item cost type (#5073)
Co-authored-by: Florian Reuth <git@florianreuth.de>
2026-09-28 08:45:15 +02:00
Nassim Jahnke 637a81e569 Handle dripstone particles dimension attribute registry data
Fixes #5074
2026-09-27 14:21:22 +02:00
Florian Reuth b4023127f6 Force set health back >0 in 1.19.1->1.19.3 (#5061) 2026-09-20 14:54:56 +02:00
Nassim Jahnke 46a61058dd Add missing tags across protocols, reduce stored tags size 2026-09-20 13:06:35 +02:00
Nassim Jahnke 66b90a5b2a Add missing tag for newly placed solid blocks letting through rain
Fixes #5060
2026-09-20 11:59:58 +02:00
Florian Reuth 8f03d6bcef Cancel axe stripping for pre 1.13, shovel dirth paths for pre 1.9 (#5057) 2026-09-20 09:44:19 +02:00
Florian Reuth e1809674fd Send brewing recipes for vanilla servers not syncing the inventory in 26.2->26.3 (#5056) 2026-09-19 19:50:12 +02:00
Pantera 4d8b0d1f54 Add missing 26.3 block tags for client predictions 2026-09-19 15:16:57 +02:00
Rocco d1a0c58f5f Restore 26.2 interpolation steps for 26.2->26.3 (#5052) 2026-09-19 12:55:02 +02:00
Dainsleif 724460d2e7 Skip repeated end credits on 1.21+ clients (#5055) 2026-09-19 12:37:59 +02:00
chico ferreira f2e3f53486 Send original client version in Velocity player details (#5043) 2026-09-19 12:20:59 +02:00
Nassim Jahnke 7190e365e4 Bump version to 5.12.1-SNAPSHOT 2026-09-19 12:20:06 +02:00
Nassim Jahnke 50aa9fa3ad 5.12.0 Release 2026-09-18 16:04:35 +02:00
Nassim Jahnke 7497103bac Null check block state Name
Shouldn't be valid, but ?
2026-09-18 16:00:13 +02:00
Nassim Jahnke ff83e2eb6e Fix brewing stand brewing time and fuel display 2026-09-18 16:00:13 +02:00
Nassim JahnkeandCamden Cove 2a75917ef5 Always create mapped chunk type
Types are cached now and need to be created in case global palette bits count changed

Co-authored-by: Camden Cove <me@camdencove.com>
2026-09-18 16:00:13 +02:00
Nassim Jahnke f634879d64 Handle ambient_particles for block state format changes 2026-09-18 16:00:13 +02:00
Nassim Jahnke e6222b38ef Replace new map decoration types when downgrading items 2026-09-18 16:00:13 +02:00
Nassim Jahnke 745a41322f Remove snapshot bit 2026-09-18 16:00:12 +02:00
Nassim Jahnke 72c679acc6 Fix expected move after teleport
Also changes the ViaCodecHandler to a MessageToMessageCodec, as otherwise sync encodes aren't properly processed due to buffering
2026-09-18 16:00:12 +02:00
Florian Reuth 5996340a33 Handle block_state_property registry changes
Fixes joining an Paper 1.8 server with 26.3

Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth a2c1841e25 Fix consume effects hashing key in 1.21.2+
Not related to the 26.3 update but easier than having to deal with merge conflicts after the public release.

Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth 3483d652e8 Update shared registrations to 26.3 changes
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth da29a96844 Replace mask type in player_chat
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:12 +02:00
Florian Reuth 735a4cacb1 Fix trim plaette id<->asset name conversion
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth d236db51e0 Fix resolvable primitive types write
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth 44167439dd Handle new type in player_action
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Nassim Jahnke 67b7ae4cac Strip namespace in 26.3->26.2 trim data 2026-09-18 16:00:11 +02:00
Florian Reuth cef5abdc73 Handle worldgen/block_state_provider going forward
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth ad7f53c3cd Fix states updating in block state provider
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:11 +02:00
Florian Reuth e5554c7a8e Handle decorated_pot block entity data
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Florian Reuth cbe42132be Fix consume effect conversion
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Florian Reuth 8023d8237b Remove compostable on item downgrade
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Florian Reuth 0611b95183 Fix pot decorations network type
Signed-off-by: Florian Reuth <git@florianreuth.de>
2026-09-18 16:00:10 +02:00
Nassim Jahnke d647f169e6 26.3-rc-2 2026-09-18 16:00:10 +02:00
Nassim Jahnke c44b94f96a Fix swing animation handling 2026-09-18 16:00:10 +02:00
Nassim Jahnke 29be35be1c 26.3-rc-1 2026-09-18 16:00:10 +02:00
Nassim Jahnke 9d2c429624 26.3-pre-3 2026-09-18 16:00:10 +02:00
Nassim Jahnke d2ab957ceb Update and restore trim material 2026-09-18 16:00:09 +02:00
Nassim Jahnke 4bbae432b4 26.3-pre-2 2026-09-18 16:00:09 +02:00
Nassim Jahnke bfc2713102 26.3-pre-1 2026-09-18 16:00:09 +02:00
Nassim Jahnke 155863a4c4 26.3-snapshot-10 2026-09-18 16:00:09 +02:00
Nassim Jahnke 8fc649fba9 26.3-snapshot-9 2026-09-18 16:00:09 +02:00
Nassim Jahnke 7edc17759f 26.3-snapshot-8 2026-09-18 16:00:08 +02:00
Nassim Jahnke b607f96988 26.3-snapshot-7 2026-09-18 16:00:08 +02:00
Nassim Jahnke f6b2f6b3ad 26.3-snapshot-6 2026-09-18 16:00:08 +02:00
Nassim Jahnke a7186fb162 26.3-snapshot-5 2026-09-18 16:00:08 +02:00
Nassim Jahnke d2e636bc6f 26.3-snapshot-4 2026-09-18 16:00:08 +02:00
Nassim Jahnke 9cbb829853 Fix movement tick offset 2026-09-18 16:00:07 +02:00
Nassim Jahnke f04f0a07a8 26.3-snapshot-3 2026-09-18 16:00:07 +02:00
Nassim Jahnke 7cf85e38c5 Fix DEBUG_SUBSCRIPTION_REQUEST and GAME_TEST_HIGHLIGHT_POS packet names 2026-09-18 16:00:07 +02:00
Nassim Jahnke 55f449ee74 Implement BlockTransformData rewrite
See code comments
2026-09-18 16:00:07 +02:00
Nassim Jahnke 460214efe2 26.3-snapshot-2 2026-09-18 16:00:07 +02:00
Nassim Jahnke e5cf0fc6c5 26.3-snapshot-1 2026-09-18 15:59:58 +02:00
Nassim Jahnke d2eed62794 Fix 1.9 identifiers file 2026-09-18 08:51:56 +02:00
Beanes 9946d3e9f6 Add 1.9 identifiers (#4976) 2026-09-16 18:08:00 +02:00
EvModder 5f98cba45b Preserve legacy world clocks (#5040) 2026-09-04 20:54:17 +02:00
LeonTG 15a7d8c853 Remove removed stats in 1.11->1.11.1 (#5037) 2026-08-30 17:19:12 +02:00
Beanes 2645d83eb7 Improve hide-scoreboard-numbers to only work for sidebar (#5034) 2026-08-29 14:34:20 +02:00
Nassim Jahnke c23ec2c26f [ci skip] Build script updates 2026-08-23 15:10:06 +02:00
Emir 42380596ee [ci skip] Use instanceof check in ConfigSection#getSerializedComponent (#5025) 2026-08-23 15:09:55 +02:00
Nassim Jahnke 03e0f231ea Fix compilation 2026-08-19 20:38:46 +02:00
Nassim Jahnke eed3de9e3d Move index to AbstractProtocol directly 2026-08-19 20:35:14 +02:00
Nassim Jahnke feb08a31a3 Skip base protocols in hasher protocol loop 2026-08-19 20:10:14 +02:00
Nassim Jahnke e8bbb5da5b Update ViaNBT 2026-08-14 16:03:56 +02:00
Nassim Jahnke 034390dd24 Update deps 2026-08-12 21:50:16 +02:00
Nassim Jahnke 89f80172b1 Move a bunch of protocol storables to direct array lookups
Also has the benefit of making them thread-safe
2026-08-05 16:57:54 +02:00
Nassim Jahnke 5f93e73b8a Create NbtOps
Useful for backup tags in VB
2026-08-05 16:09:13 +02:00
Nassim Jahnke c124b309e0 Ignore invalid legacy show_item in 1.11->1.12
Closes #5014
2026-07-30 09:17:59 +02:00
Nassim Jahnke 122b81dd33 Add shears breaking speed block tags in 26.1->26.2
Fixes #5010
2026-07-23 17:46:09 +02:00
Nassim Jahnke a2896b64fa Fix 1.21.11->26.1 damage_resistant rewriting
Fixes #5008
2026-07-23 16:13:03 +02:00
Nassim Jahnke 2d78597a59 Handle nested identifiers in item hover events
Actually rewrite the important ones (i.e. relevant to tooltips) and remove the others.
2026-07-23 15:23:33 +02:00
Nassim Jahnke 432918645e Fix boat rotation unpacking in 1.21->1.21.2 2026-07-18 19:24:44 +02:00
RiceChen_andNassim Jahnke c20c29fa3a Sort stonecutter recipes by output registry key (#5006)
Fixes #4242

Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2026-07-15 16:58:08 +02:00
Nassim Jahnke ab85b0e0f0 Build script cleanup
This also moves Fabric and Sponge resource files into the universal dir; we do not publish platform specific jars and this otherwise only leads to a more complicated project setup
2026-07-15 13:12:58 +02:00
Nassim Jahnke 3a5d9541c8 Use netty Buf I/O streams on Java 24+
The JDK had already gotten similar (but much better still) allocation and performance improvements to read and writeUtf methods
2026-07-14 12:39:49 +02:00
Nassim Jahnke 356a5e25f4 Bump version to 5.11.1-SNAPSHOT 2026-07-14 12:05:55 +02:00
267 changed files with 6157 additions and 999 deletions

No files matched your search

+3 -2
View File
@@ -1,4 +1,5 @@
version: 2
# Disabled for the time being, being done manually instead
updates:
- package-ecosystem: "github-actions"
cooldown:
@@ -6,11 +7,11 @@ updates:
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
open-pull-requests-limit: 0
- package-ecosystem: "gradle"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
open-pull-requests-limit: 0
+3 -3
View File
@@ -11,16 +11,16 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
uses: gradle/actions/setup-gradle@v6.3.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v5.5.0
uses: actions/setup-java@v5.7.0
with:
distribution: 'temurin'
java-version: 17
+3 -3
View File
@@ -16,16 +16,16 @@ jobs:
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
uses: gradle/actions/setup-gradle@v6.3.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v5.5.0
uses: actions/setup-java@v5.7.0
with:
distribution: 'temurin'
java-version: 17
+2
View File
@@ -37,3 +37,5 @@ bin/
run/
AGENTS.override.md
.claude/
!.claude/CLAUDE.md
@@ -508,7 +508,7 @@ public interface ViaVersionConfig extends Config {
boolean cancelBlockSounds();
/**
* Hides scoreboard numbers for 1.20.3+ clients on older server versions.
* Hides sidebar scoreboard numbers for 1.20.3+ clients on older server versions.
*
* @return true if enabled
*/
@@ -0,0 +1,45 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.connection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
/**
* Holds protocol-specific data. Protocols may extend the data wrapper to hold extra data.
*/
public interface ProtocolStorables {
EntityTracker entityTracker();
void setEntityTracker(EntityTracker tracker);
ClientWorld clientWorld();
void setClientWorld(ClientWorld clientWorld);
ItemHasher itemHasher();
void setItemHasher(ItemHasher itemHasher);
}
@@ -22,6 +22,8 @@
*/
package com.viaversion.viaversion.api.connection;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
@@ -36,18 +38,18 @@ import io.netty.channel.ChannelFuture;
import io.netty.handler.codec.CodecException;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface UserConnection {
/**
* Get an object from the storage.
* Get an object from the storage. Useful where protocol instances aren't readily available.
*
* @param objectClass The class of the object to get
* @param <T> The type of the class you want to get.
* @return The requested object
* @see #storables(Protocol)
*/
@Nullable <T extends StorableObject> T get(Class<T> objectClass);
@@ -69,27 +71,56 @@ public interface UserConnection {
@Nullable <T extends StorableObject> T remove(Class<T> objectClass);
/**
* Put an object into the stored objects based on class.
* Put an object into the stored objects based on class. Useful where protocol instances aren't readily available.
*
* @param object The object to store.
* @see #storables(Protocol)
*/
void put(StorableObject object);
/**
* Holds protocol-specific data. Where protocol instances aren't readily available, use {@link #put(StorableObject)}.
*
* @param protocol protocol
* @param <T> protocol-specific storables type
* @return protocol storables
* @throws IllegalArgumentException if the protocol does not have a valid return value for {@link Protocol#index()}
*/
<T extends ProtocolStorables> T storables(Protocol<?, ?, ?, ?> protocol);
/**
* Holds protocol-specific data. Prefer using {@link #storables(Protocol)} where possible.
*
* @param protocolClass protocol class
* @param <T> protocol-specific storables type
* @return protocol storables
* @throws IllegalArgumentException if the protocol does not have a valid return value for {@link Protocol#index()}
* @see #storables(Protocol)
*/
default <T extends ProtocolStorables> T storables(final Class<? extends Protocol> protocolClass) {
return storables(Via.getManager().getProtocolManager().getProtocol(protocolClass));
}
/**
* Returns a collection of entity trackers currently registered.
*
* @return collection of entity trackers currently registered
*/
@Deprecated(forRemoval = true)
Collection<EntityTracker> getEntityTrackers();
@Deprecated(forRemoval = true)
@Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass);
/**
* Returns the entity tracker by the given protocol class if present.
*
* @param protocolClass protocol class
* @param <T> entity tracker type
* @param protocol protocol
* @param <T> entity tracker type
* @return entity tracker if present
* @see com.viaversion.viaversion.api.rewriter.EntityRewriter#tracker(UserConnection)
*/
@Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass);
@Nullable <T extends EntityTracker> T getEntityTracker(Protocol<?, ?, ?, ?> protocol);
/**
* Adds an entity tracker to the user connection.
@@ -97,34 +128,43 @@ public interface UserConnection {
*
* @param protocolClass protocol class
* @param tracker entity tracker
* @deprecated use {@link #storables(Protocol)}
*/
@Deprecated(forRemoval = true)
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
/**
* Returns the item hasher by the given class if present.
*
* @param protocol protocol
* @param <T> item hasher type
* @return item hasher if present
*/
@Nullable <T extends ItemHasher> T getItemHasher(Protocol<?, ?, ?, ?> protocol);
/**
* Adds an item hasher to the user connection.
*
* @param protocolClass protocol class
* @param itemHasher item hasher
* @deprecated use {@link #storables(Protocol)}
*/
@Deprecated(forRemoval = true)
void addItemHasher(Class<? extends Protocol> protocolClass, ItemHasher itemHasher);
/**
* Returns the item hasher by the given protocol class if present.
*
* @param protocolClass protocol class
* @param <T> item hasher type
* @return item hasher if present
*/
@Deprecated(forRemoval = true)
@Nullable <T extends ItemHasher> T getItemHasher(Class<? extends Protocol> protocolClass);
/**
* Returns the client world by the given protocol class if present.
* Returns the client world by the given class if present.
*
* @param protocolClass protocol class
* @param <T> client world type
* @return client world if present
* @deprecated use {@link #storables(Protocol)}
*/
@Nullable
@Deprecated(forRemoval = true)
<T extends ClientWorld> T getClientWorld(Class<? extends Protocol> protocolClass);
/**
@@ -134,6 +174,7 @@ public interface UserConnection {
* @param protocolClass protocol class
* @param clientWorld client world
*/
@Deprecated(forRemoval = true)
void addClientWorld(Class<? extends Protocol> protocolClass, ClientWorld clientWorld);
/**
@@ -26,6 +26,8 @@ import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.function.IntConsumer;
@@ -49,6 +51,12 @@ public final class IdRanges {
return ids;
}
public static IntList decodeAsList(final ByteArrayTag rangesTag) {
final IntList ids = new IntArrayList();
forEachId(rangesTag, ids::add);
return ids;
}
public static void forEachId(final ByteArrayTag rangesTag, final IntConsumer consumer) {
final ByteBuf buf = Unpooled.wrappedBuffer(rangesTag.getValue());
int prevEnd = 0;
@@ -191,6 +191,10 @@ public interface MappingData {
*/
@Nullable IntSet changedBlocks();
default boolean hasBlockChanged(final int blockId) {
return changedBlocks() != null && changedBlocks().contains(blockId);
}
@Nullable Set<String> changedEnvironmentAttributes();
/**
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.ListTag;
@@ -198,8 +199,14 @@ public class MappingDataBase implements MappingData {
final List<TagData> tagsList = new ArrayList<>(tags.size());
for (final Map.Entry<String, Tag> entry : tag.entrySet()) {
final IntArrayTag entries = (IntArrayTag) entry.getValue();
tagsList.add(new TagData(entry.getKey(), entries.getValue()));
final int[] entries;
if (entry.getValue() instanceof final ByteArrayTag rangesTag) {
entries = IdRanges.decodeAsList(rangesTag).toIntArray();
} else {
// Old format / if the values need to be sorted
entries = ((IntArrayTag) entry.getValue()).getValue();
}
tagsList.add(new TagData(entry.getKey(), entries));
}
this.tags.put(type, tagsList);
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.EitherImpl;
public final class ResolvableFloat extends EitherImpl<Float, String> {
private ResolvableFloat(final Float left, final String right) {
super(left, right);
}
public static ResolvableFloat of(final String value) {
return new ResolvableFloat(null, value);
}
public static ResolvableFloat of(final Float value) {
return new ResolvableFloat(value, null);
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.EitherImpl;
public final class ResolvableInt extends EitherImpl<Integer, String> {
private ResolvableInt(final Integer left, final String right) {
super(left, right);
}
public static ResolvableInt of(final String value) {
return new ResolvableInt(null, value);
}
public static ResolvableInt of(final Integer value) {
return new ResolvableInt(value, null);
}
}
@@ -110,7 +110,7 @@ public final class DataPaletteImpl implements DataPalette {
* Stores palette indexes from a compact long array, replacing all current values.
* The data is kept packed unless written to; reads extract bits the slow way, since almost all work will use replaceIds or will only have a few reads.
* <p>
* Only valid for local palettes (bitsPerValue <= 8).
* Only valid for local palettes (bitsPerValue &lt;= 8).
*
* @param data compact long array
* @param bitsPerValue bits per value
@@ -38,6 +38,8 @@ public interface CodecContext {
UserConnection connection();
Protocol<?, ?, ?, ?> protocol();
interface RegistryAccess {
UserConnection connection();
@@ -58,7 +58,9 @@ public interface Ops {
void writeMap(Consumer<MapSerializer> consumer);
<V> void write(final Type<V> type, final V value);
default <V> void write(final Type<V> type, final V value) {
type.write(this, value);
}
interface ListSerializer {
@@ -35,10 +35,11 @@ import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_11;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_2;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_5;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.AdventureModePredicate;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrim;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrim1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrim26_3;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrimMaterial1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ArmorTrimMaterial26_3;
import com.viaversion.viaversion.api.minecraft.item.data.AttackRange;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
@@ -47,7 +48,10 @@ 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.BlockStateProperties;
import com.viaversion.viaversion.api.minecraft.item.data.BlocksAttacks;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.BrewingFuel;
import com.viaversion.viaversion.api.minecraft.item.data.Compostable;
import com.viaversion.viaversion.api.minecraft.item.data.consumable.Consumable1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.CookingFuel;
import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant1_21_2;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant26_1;
@@ -72,12 +76,14 @@ import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable.Jukebox
import com.viaversion.viaversion.api.minecraft.item.data.KineticWeapon;
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.MobVisibility;
import com.viaversion.viaversion.api.minecraft.item.data.PiercingWeapon;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesBannerPatterns;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.trim.ProvidesTrimMaterial1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.Repairable;
import com.viaversion.viaversion.api.minecraft.item.data.SignText;
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
import com.viaversion.viaversion.api.minecraft.item.data.SwingAnimation;
import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
@@ -86,6 +92,7 @@ import com.viaversion.viaversion.api.minecraft.item.data.TropicalFishPattern;
import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable;
import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
import com.viaversion.viaversion.api.minecraft.item.data.UseEffects;
import com.viaversion.viaversion.api.minecraft.item.data.VillagerFood;
import com.viaversion.viaversion.api.minecraft.item.data.Weapon;
import com.viaversion.viaversion.api.minecraft.item.data.WritableBook;
import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
@@ -145,7 +152,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_20_5 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_20_5);
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_21);
public static final StructuredDataKey<FoodProperties1_21_2> FOOD1_21_2 = new StructuredDataKey<>("food", FoodProperties1_21_2.TYPE);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE1_21_2);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE26_3 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE26_3);
public static final StructuredDataKey<UseCooldown> USE_COOLDOWN = new StructuredDataKey<>("use_cooldown", UseCooldown.TYPE);
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
public static final StructuredDataKey<DamageResistant1_21_2> DAMAGE_RESISTANT1_21_2 = new StructuredDataKey<>("damage_resistant", DamageResistant1_21_2.TYPE);
@@ -161,13 +169,18 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
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.IDENTIFIER);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION1_21_2 = new StructuredDataKey<>("death_protection", DeathProtection.TYPE1_21_2);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION26_3 = new StructuredDataKey<>("death_protection", DeathProtection.TYPE26_3);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS1_21_5 = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE1_21_5);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS26_1 = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.TYPE26_1);
public static final StructuredDataKey<PiercingWeapon> PIERCING_WEAPON = new StructuredDataKey<>("piercing_weapon", PiercingWeapon.TYPE);
public static final StructuredDataKey<KineticWeapon> KINETIC_WEAPON = new StructuredDataKey<>("kinetic_weapon", KineticWeapon.TYPE);
public static final StructuredDataKey<SwingAnimation> SWING_ANIMATION = new StructuredDataKey<>("swing_animation", SwingAnimation.TYPE);
public static final StructuredDataKey<SwingAnimation> ATTACK_ANIMATION = new StructuredDataKey<>("attack_animation", SwingAnimation.TYPE);
public static final StructuredDataKey<SwingAnimation> INTERACT_ANIMATION = new StructuredDataKey<>("interact_animation", SwingAnimation.TYPE);
public static final StructuredDataKey<Integer> ADDITIONAL_TRADE_COST = new StructuredDataKey<>("additional_trade_cost", Types.VAR_INT);
public static final StructuredDataKey<Integer> BLOCK_TRANSFORMER = new StructuredDataKey<>("block_transformer", new SynchronizedRegistryValueType(RegistryKey.of("block_transformer")));
public static final StructuredDataKey<VillagerFood> VILLAGER_FOOD = new StructuredDataKey<>("villager_food", VillagerFood.TYPE);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS1_20_5 = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE1_20_5);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS1_21_5 = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE1_21_5);
public static final StructuredDataKey<Integer> DYE = new StructuredDataKey<>("dye", EnumTypes.DYE_COLOR);
@@ -183,10 +196,11 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<SuspiciousStewEffect[]> SUSPICIOUS_STEW_EFFECTS = new StructuredDataKey<>("suspicious_stew_effects", SuspiciousStewEffect.ARRAY_TYPE);
public static final StructuredDataKey<WritableBook> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", WritableBook.TYPE);
public static final StructuredDataKey<WrittenBook> WRITTEN_BOOK_CONTENT = new StructuredDataKey<>("written_book_content", WrittenBook.TYPE);
public static final StructuredDataKey<ArmorTrim> TRIM1_20_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_20_5);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_2 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_2);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_4 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_4);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_5);
public static final StructuredDataKey<ArmorTrim1_20_5> TRIM1_20_5 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_20_5);
public static final StructuredDataKey<ArmorTrim1_20_5> TRIM1_21_2 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_21_2);
public static final StructuredDataKey<ArmorTrim1_20_5> TRIM1_21_4 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_21_4);
public static final StructuredDataKey<ArmorTrim1_20_5> TRIM1_21_5 = new StructuredDataKey<>("trim", ArmorTrim1_20_5.TYPE1_21_5);
public static final StructuredDataKey<ArmorTrim26_3> TRIM26_3 = new StructuredDataKey<>("trim", ArmorTrim26_3.TYPE);
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);
@@ -194,11 +208,13 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<CompoundTag> BLOCK_ENTITY_DATA1_20_5 = new StructuredDataKey<>("block_entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<BlockEntityData> BLOCK_ENTITY_DATA1_21_9 = new StructuredDataKey<>("block_entity_data", BlockEntityData.TYPE);
public static final StructuredDataKey<Holder<Instrument1_20_5>> INSTRUMENT1_20_5 = new StructuredDataKey<>("instrument", Instrument1_20_5.TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT1_21_2 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT1_21_2 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE1_21_2);
public static final StructuredDataKey<EitherHolder<Instrument1_21_2>> INSTRUMENT1_21_5 = new StructuredDataKey<>("instrument", Instrument1_21_2.EITHER_HOLDER_TYPE);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT26_1 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
public static final StructuredDataKey<ProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL1_21_5 = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial.TYPE);
public static final StructuredDataKey<Holder<ArmorTrimMaterial>> PROVIDES_TRIM_MATERIAL26_1 = new StructuredDataKey<>("provides_trim_material", ArmorTrimMaterial.TYPE1_21_5);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT26_1 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE1_21_2);
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT26_3 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE26_3);
public static final StructuredDataKey<ProvidesTrimMaterial1_20_5> PROVIDES_TRIM_MATERIAL1_21_5 = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial1_20_5.TYPE);
public static final StructuredDataKey<Holder<ArmorTrimMaterial1_20_5>> PROVIDES_TRIM_MATERIAL26_1 = new StructuredDataKey<>("provides_trim_material", ArmorTrimMaterial1_20_5.TYPE1_21_5);
public static final StructuredDataKey<Holder<ArmorTrimMaterial26_3>> PROVIDES_TRIM_MATERIAL26_3 = new StructuredDataKey<>("provides_trim_material", ArmorTrimMaterial26_3.TYPE);
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21_5 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21_5);
@@ -214,7 +230,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Key> NOTE_BLOCK_SOUND = new StructuredDataKey<>("note_block_sound", Types.IDENTIFIER);
public static final StructuredDataKey<BannerPatternLayer[]> BANNER_PATTERNS = new StructuredDataKey<>("banner_patterns", BannerPatternLayer.ARRAY_TYPE);
public static final StructuredDataKey<Integer> BASE_COLOR = new StructuredDataKey<>("base_color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
public static final StructuredDataKey<PotDecorations1_20_5> POT_DECORATIONS1_20_5 = new StructuredDataKey<>("pot_decorations", PotDecorations1_20_5.TYPE);
// 26.3+ pot decorations are in their own key classes
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);
@@ -222,6 +239,15 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
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);
public static final StructuredDataKey<Compostable> COMPOSTABLE = new StructuredDataKey<>("compostable", Compostable.TYPE);
public static final StructuredDataKey<CookingFuel> COOKING_FUEL = new StructuredDataKey<>("cooking_fuel", CookingFuel.TYPE);
public static final StructuredDataKey<BrewingFuel> BREWING_FUEL = new StructuredDataKey<>("brewing_fuel", BrewingFuel.TYPE);
public static final StructuredDataKey<MobVisibility> MOB_VISIBILITY = new StructuredDataKey<>("mob_visibility", MobVisibility.TYPE);
public static final StructuredDataKey<Integer> PROVIDES_POTTERY_PATTERN = new StructuredDataKey<>("provides_pottery_pattern", new SynchronizedRegistryValueType(RegistryKey.of("decorated_pot_pattern")));
public static final StructuredDataKey<SignText> SIGN_TEXT_FRONT = new StructuredDataKey<>("sign_text_front", SignText.TYPE);
public static final StructuredDataKey<SignText> SIGN_TEXT_BACK = new StructuredDataKey<>("sign_text_back", SignText.TYPE);
public static final StructuredDataKey<Unit> WAXED = new StructuredDataKey<>("waxed", Types.EMPTY);
public static final StructuredDataKey<Integer> CUSHION_COLOR = new StructuredDataKey<>("cushion/color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> VILLAGER_VARIANT = new StructuredDataKey<>("villager/variant", EnumTypes.VILLAGER_TYPE);
public static final StructuredDataKey<Integer> WOLF_VARIANT = new StructuredDataKey<>("wolf/variant", new SynchronizedRegistryValueType(RegistryKey.of("wolf_variant")));
@@ -0,0 +1,37 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.data.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations26_3;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys26_3 extends StructuredDataKeys26_2 {
public final StructuredDataKey<PotDecorations26_3> potDecorations;
public StructuredDataKeys26_3(final VersionedTypesHolder types) {
super(types);
this.potDecorations = add("pot_decorations", new PotDecorations26_3.PotDecorationsType(types.optionalItemTemplate()));
}
}
@@ -0,0 +1,336 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entities;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.EntityTypeUtil;
import com.viaversion.viaversion.util.Key;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum EntityTypes26_3 implements EntityType {
ENTITY(null, null),
AREA_EFFECT_CLOUD(ENTITY),
END_CRYSTAL(ENTITY),
EVOKER_FANGS(ENTITY),
EXPERIENCE_ORB(ENTITY),
EYE_OF_ENDER(ENTITY),
FALLING_BLOCK(ENTITY),
ITEM(ENTITY),
TNT(ENTITY),
OMINOUS_ITEM_SPAWNER(ENTITY),
MARKER(ENTITY),
LIGHTNING_BOLT(ENTITY),
INTERACTION(ENTITY),
DISPLAY(ENTITY, null),
BLOCK_DISPLAY(DISPLAY),
ITEM_DISPLAY(DISPLAY),
TEXT_DISPLAY(DISPLAY),
// Hanging entities
HANGING_ENTITY(ENTITY, null),
LEASH_KNOT(HANGING_ENTITY),
PAINTING(HANGING_ENTITY),
ITEM_FRAME(HANGING_ENTITY),
GLOW_ITEM_FRAME(ITEM_FRAME),
CUSHION(ENTITY),
// Projectiles
PROJECTILE(ENTITY, null),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
FIREWORK_ROCKET(PROJECTILE),
LLAMA_SPIT(PROJECTILE),
SHULKER_BULLET(PROJECTILE),
FISHING_BOBBER(PROJECTILE),
WITHER_SKULL(PROJECTILE),
DRAGON_FIREBALL(PROJECTILE), // Doesn't actually inherit fireball
ABSTRACT_THROWN_POTION(ITEM_PROJECTILE, null),
SPLASH_POTION(ABSTRACT_THROWN_POTION),
LINGERING_POTION(ABSTRACT_THROWN_POTION),
ABSTRACT_ARROW(PROJECTILE, null),
ARROW(ABSTRACT_ARROW),
SPECTRAL_ARROW(ABSTRACT_ARROW),
TRIDENT(ABSTRACT_ARROW),
ABSTRACT_FIREBALL(ENTITY, null),
FIREBALL(ABSTRACT_FIREBALL),
SMALL_FIREBALL(ABSTRACT_FIREBALL),
ABSTRACT_WIND_CHARGE(PROJECTILE, null),
WIND_CHARGE(ABSTRACT_WIND_CHARGE),
BREEZE_WIND_CHARGE(ABSTRACT_WIND_CHARGE),
// Vehicles
VEHICLE(ENTITY, null),
ABSTRACT_MINECART(VEHICLE, null),
MINECART(ABSTRACT_MINECART),
FURNACE_MINECART(ABSTRACT_MINECART),
COMMAND_BLOCK_MINECART(ABSTRACT_MINECART),
TNT_MINECART(ABSTRACT_MINECART),
SPAWNER_MINECART(ABSTRACT_MINECART),
ABSTRACT_MINECART_CONTAINER(ABSTRACT_MINECART, null),
CHEST_MINECART(ABSTRACT_MINECART_CONTAINER),
HOPPER_MINECART(ABSTRACT_MINECART_CONTAINER),
ABSTRACT_BOAT(VEHICLE, null),
ABSTRACT_CHEST_BOAT(ABSTRACT_BOAT, null),
ACACIA_BOAT(ABSTRACT_BOAT),
ACACIA_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
BAMBOO_CHEST_RAFT(ABSTRACT_CHEST_BOAT),
BAMBOO_RAFT(ABSTRACT_BOAT),
BIRCH_BOAT(ABSTRACT_BOAT),
BIRCH_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
CHERRY_BOAT(ABSTRACT_BOAT),
CHERRY_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
DARK_OAK_BOAT(ABSTRACT_BOAT),
DARK_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
JUNGLE_BOAT(ABSTRACT_BOAT),
JUNGLE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
MANGROVE_BOAT(ABSTRACT_BOAT),
MANGROVE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
OAK_BOAT(ABSTRACT_BOAT),
OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
PALE_OAK_BOAT(ABSTRACT_BOAT),
PALE_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
SPRUCE_BOAT(ABSTRACT_BOAT),
SPRUCE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
POPLAR_BOAT(ABSTRACT_BOAT),
POPLAR_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
// Living entities as a larger subclass
LIVING_ENTITY(ENTITY, null),
ARMOR_STAND(LIVING_ENTITY),
// Players
AVATAR(LIVING_ENTITY, null),
MANNEQUIN(AVATAR),
PLAYER(AVATAR),
// Mobs as a larger subclass
MOB(LIVING_ENTITY, null),
ENDER_DRAGON(MOB),
// Ambient mobs
AMBIENT_CREATURE(MOB, null),
BAT(AMBIENT_CREATURE),
// Flying mobs
FLYING_MOB(MOB, null),
GHAST(FLYING_MOB),
PHANTOM(FLYING_MOB),
// Pathfinder mobs and its subclasses
PATHFINDER_MOB(MOB, null),
ALLAY(PATHFINDER_MOB),
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
SNOW_GOLEM(ABSTRACT_GOLEM),
IRON_GOLEM(ABSTRACT_GOLEM),
SHULKER(ABSTRACT_GOLEM),
COPPER_GOLEM(ABSTRACT_GOLEM),
// Ageable mobs and (tamable) animals
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
VILLAGER(ABSTRACT_VILLAGER),
WANDERING_TRADER(ABSTRACT_VILLAGER),
ABSTRACT_CUBE_MOB(ABSTRACT_AGEABLE, null),
SLIME(ABSTRACT_CUBE_MOB),
MAGMA_CUBE(ABSTRACT_CUBE_MOB),
SULFUR_CUBE(ABSTRACT_CUBE_MOB),
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
AXOLOTL(ABSTRACT_ANIMAL),
CHICKEN(ABSTRACT_ANIMAL),
PANDA(ABSTRACT_ANIMAL),
PIG(ABSTRACT_ANIMAL),
POLAR_BEAR(ABSTRACT_ANIMAL),
RABBIT(ABSTRACT_ANIMAL),
SHEEP(ABSTRACT_ANIMAL),
BEE(ABSTRACT_ANIMAL),
TURTLE(ABSTRACT_ANIMAL),
FOX(ABSTRACT_ANIMAL),
FROG(ABSTRACT_ANIMAL),
GOAT(ABSTRACT_ANIMAL),
HOGLIN(ABSTRACT_ANIMAL),
STRIDER(ABSTRACT_ANIMAL),
SNIFFER(ABSTRACT_ANIMAL),
ARMADILLO(ABSTRACT_ANIMAL),
HAPPY_GHAST(ABSTRACT_ANIMAL),
OCELOT(ABSTRACT_ANIMAL),
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
COW(ABSTRACT_COW),
MOOSHROOM(ABSTRACT_COW),
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
CAT(TAMABLE_ANIMAL),
WOLF(TAMABLE_ANIMAL),
PARROT(TAMABLE_ANIMAL),
ABSTRACT_NAUTILUS(TAMABLE_ANIMAL, null),
NAUTILUS(ABSTRACT_NAUTILUS),
ZOMBIE_NAUTILUS(ABSTRACT_NAUTILUS),
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
HORSE(ABSTRACT_HORSE),
SKELETON_HORSE(ABSTRACT_HORSE),
ZOMBIE_HORSE(ABSTRACT_HORSE),
CAMEL(ABSTRACT_HORSE),
CAMEL_HUSK(CAMEL),
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
DONKEY(ABSTRACT_CHESTED_HORSE),
MULE(ABSTRACT_CHESTED_HORSE),
LLAMA(ABSTRACT_CHESTED_HORSE),
TRADER_LLAMA(LLAMA),
// Monsters
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
BLAZE(ABSTRACT_MONSTER),
CREEPER(ABSTRACT_MONSTER),
ENDERMITE(ABSTRACT_MONSTER),
ENDERMAN(ABSTRACT_MONSTER),
GIANT(ABSTRACT_MONSTER),
SILVERFISH(ABSTRACT_MONSTER),
VEX(ABSTRACT_MONSTER),
WITHER(ABSTRACT_MONSTER),
BREEZE(ABSTRACT_MONSTER),
ZOGLIN(ABSTRACT_MONSTER),
WARDEN(ABSTRACT_MONSTER),
CREAKING(ABSTRACT_MONSTER),
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
SKELETON(ABSTRACT_SKELETON),
STRAY(ABSTRACT_SKELETON),
WITHER_SKELETON(ABSTRACT_SKELETON),
BOGGED(ABSTRACT_SKELETON),
PARCHED(ABSTRACT_SKELETON),
ZOMBIE(ABSTRACT_MONSTER),
DROWNED(ZOMBIE),
HUSK(ZOMBIE),
ZOMBIFIED_PIGLIN(ZOMBIE),
ZOMBIE_VILLAGER(ZOMBIE),
GUARDIAN(ABSTRACT_MONSTER),
ELDER_GUARDIAN(GUARDIAN),
SPIDER(ABSTRACT_MONSTER),
CAVE_SPIDER(SPIDER),
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
PIGLIN(ABSTRACT_PIGLIN),
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
// Water mobs
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
DOLPHIN(AGEABLE_WATER_CREATURE),
SQUID(AGEABLE_WATER_CREATURE),
GLOW_SQUID(SQUID),
WATER_ANIMAL(PATHFINDER_MOB, null),
ABSTRACT_FISH(WATER_ANIMAL, null),
PUFFERFISH(ABSTRACT_FISH),
TADPOLE(ABSTRACT_FISH),
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
COD(ABSTRACT_SCHOOLING_FISH),
SALMON(ABSTRACT_SCHOOLING_FISH),
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
// Raiders
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
WITCH(ABSTRACT_RAIDER),
RAVAGER(ABSTRACT_RAIDER),
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
VINDICATOR(ABSTRACT_ILLAGER),
PILLAGER(ABSTRACT_ILLAGER),
EVOKER(SPELLCASTER_ILLAGER),
ILLUSIONER(SPELLCASTER_ILLAGER);
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
private final EntityType parent;
private final String identifier;
private int id = -1;
EntityTypes26_3(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes26_3(final EntityType parent, @Nullable final String identifier) {
this.parent = parent;
this.identifier = identifier;
}
@Override
public int getId() {
if (id == -1) {
throw new IllegalStateException("Ids have not been initialized yet (type " + name() + ")");
}
return id;
}
@Override
public String identifier() {
Preconditions.checkArgument(identifier != null, "Called identifier method on abstract type");
return identifier;
}
@Override
public @Nullable EntityType getParent() {
return parent;
}
@Override
public boolean isAbstractType() {
return identifier == null;
}
public static EntityType getTypeFromId(final int typeId) {
return EntityTypeUtil.getTypeFromId(TYPES, typeId, PIG);
}
public static void initialize(final Protocol<?, ?, ?, ?> protocol) {
EntityTypeUtil.initialize(values(), TYPES, protocol, (type, id) -> type.id = id);
}
}
@@ -0,0 +1,83 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes26_3 extends AbstractEntityDataTypes {
public final EntityDataType byteType = add(0, Types.BYTE);
public final EntityDataType varIntType = add(1, Types.VAR_INT);
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TRUSTED_TAG);
public final EntityDataType optionalComponentType = add(6, Types.TRUSTED_OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
public final EntityDataType blockPositionType = add(10, Types.BLOCK_POSITION1_14);
public final EntityDataType optionalBlockPositionType = add(11, Types.OPTIONAL_POSITION_1_14);
public final EntityDataType directionType = add(12, Types.VAR_INT);
public final EntityDataType optionalUUIDType = add(13, Types.OPTIONAL_UUID);
public final EntityDataType blockStateType = add(14, Types.VAR_INT);
public final EntityDataType optionalBlockStateType = add(15, Types.VAR_INT);
public final EntityDataType particleType;
public final EntityDataType particlesType;
public final EntityDataType villagerDataType = add(18, Types.VILLAGER_DATA);
public final EntityDataType optionalVarIntType = add(19, Types.OPTIONAL_VAR_INT);
public final EntityDataType poseType = add(20, Types.VAR_INT);
public final EntityDataType catVariantType = add(21, Types.VAR_INT);
public final EntityDataType catSoundVariant = add(22, Types.VAR_INT);
public final EntityDataType cowVariantType = add(23, Types.VAR_INT);
public final EntityDataType cowSoundVariant = add(24, Types.VAR_INT);
public final EntityDataType wolfVariantType = add(25, Types.VAR_INT);
public final EntityDataType wolfSoundVariantType = add(26, Types.VAR_INT);
public final EntityDataType frogVariantType = add(27, Types.VAR_INT);
public final EntityDataType pigVariantType = add(28, Types.VAR_INT);
public final EntityDataType pigSoundVariant = add(29, Types.VAR_INT);
public final EntityDataType chickenVariantType = add(30, Types.VAR_INT);
public final EntityDataType chickenSoundVariant = add(31, Types.VAR_INT);
public final EntityDataType zombieNautilusVariantType = add(32, Types.VAR_INT);
public final EntityDataType optionalGlobalPosition = add(33, Types.OPTIONAL_GLOBAL_POSITION);
public final EntityDataType paintingVariantType = add(34, PaintingVariant.TYPE1_21_2);
public final EntityDataType snifferState = add(35, Types.VAR_INT);
public final EntityDataType armadilloState = add(36, Types.VAR_INT);
public final EntityDataType copperGolemState = add(37, Types.VAR_INT);
public final EntityDataType weatheringCopperState = add(38, Types.VAR_INT);
public final EntityDataType vector3FType = add(39, Types.VECTOR3F);
public final EntityDataType quaternionType = add(40, Types.QUATERNION);
public final EntityDataType mannequinProfileType = add(41, Types.RESOLVABLE_PROFILE);
public final EntityDataType humanoidArmType = add(42, Types.VAR_INT);
public final EntityDataType dyeColorType = add(43, Types.VAR_INT);
public EntityDataTypes26_3(final VersionedTypesHolder types) {
super(44);
this.itemType = add(7, types.item());
this.particleType = add(16, types.particle());
this.particlesType = add(17, types.particles());
}
}
@@ -0,0 +1,126 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.data.MappingData.MappingType;
import com.viaversion.viaversion.api.minecraft.Holder;
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.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
// TODO move block state provider rewriting to registry data rewriter
public record BlockTransformData(CompoundTag blockStateProvider, Holder<SoundEvent> sound, int transformParticle,
int[] disallowedFaces, @Nullable String loot, int dropStrategy,
boolean updateFromNeighbors, int transformType,
boolean consumeOnUse, int itemDamagePerUse) implements Rewritable, Copyable {
public static final Type<BlockTransformData> TYPE = new Type<>(BlockTransformData.class) {
@Override
public BlockTransformData read(final ByteBuf buffer) {
final CompoundTag blockStateProvider = Types.COMPOUND_TAG.read(buffer);
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
final int transformParticle = Types.VAR_INT.readPrimitive(buffer);
final int[] disallowedFaces = Types.VAR_INT_ARRAY_PRIMITIVE.read(buffer);
final String loot = Types.OPTIONAL_STRING.read(buffer);
final int dropStrategy = Types.VAR_INT.readPrimitive(buffer);
final boolean updateFromNeighbors = Types.BOOLEAN.read(buffer);
final int transformType = Types.VAR_INT.readPrimitive(buffer);
final boolean consumeOnUse = Types.BOOLEAN.read(buffer);
final int itemDamagePerUse = Types.VAR_INT.readPrimitive(buffer);
return new BlockTransformData(blockStateProvider, sound, transformParticle, disallowedFaces, loot, dropStrategy, updateFromNeighbors, transformType, consumeOnUse, itemDamagePerUse);
}
@Override
public void write(final ByteBuf buffer, final BlockTransformData value) {
Types.COMPOUND_TAG.write(buffer, value.blockStateProvider);
Types.SOUND_EVENT.write(buffer, value.sound);
Types.VAR_INT.writePrimitive(buffer, value.transformParticle);
Types.VAR_INT_ARRAY_PRIMITIVE.write(buffer, value.disallowedFaces);
Types.OPTIONAL_STRING.write(buffer, value.loot);
Types.VAR_INT.writePrimitive(buffer, value.dropStrategy);
Types.BOOLEAN.write(buffer, value.updateFromNeighbors);
Types.VAR_INT.writePrimitive(buffer, value.transformType);
Types.BOOLEAN.write(buffer, value.consumeOnUse);
Types.VAR_INT.writePrimitive(buffer, value.itemDamagePerUse);
}
@Override
public void write(final Ops ops, final BlockTransformData data) {
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingType.SOUND, "intentionally_empty"));
ops.writeMap(map -> map
.write("block_state_provider", Types.COMPOUND_TAG, data.blockStateProvider)
.writeOptional("sound", Types.SOUND_EVENT, data.sound, defaultSound)
.writeOptional("particle", EnumTypes.TRANSFORM_PARTICLE, data.transformParticle, 0)
.writeOptional("disallowed_faces", EnumTypes.DIRECTION.new EnumArrayType(), data.disallowedFaces, new int[0])
.writeOptional("loot", Types.STRING, data.loot)
.writeOptional("drop_strategy", Types.VAR_INT, data.dropStrategy, 1)
.writeOptional("update_from_neighbors", Types.BOOLEAN, data.updateFromNeighbors, true)
.writeOptional("transform_type", Types.VAR_INT, data.transformType, 0)
.writeOptional("consume_on_use", Types.BOOLEAN, data.consumeOnUse, true)
.writeOptional("item_damage_per_use", Types.VAR_INT, data.itemDamagePerUse, 0)
);
}
};
public static final ArrayType<BlockTransformData> ARRAY_TYPE = new ArrayType<>(TYPE);
@Override
public BlockTransformData rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
CompoundTag updatedTag = blockStateProvider().copy();
if (protocol.getRegistryDataRewriter().updateBlockStateProvider(updatedTag)) {
// Back it up clientbound so server data doesn't disappear; remove it for newly spawned items serverbound.
// Given it's not even encoded properly over the network and would otherwise require keeping full block state mappings
// and is not needed on the client, we only do the bare minimum to guarantee compatibility.
if (clientbound) {
updatedTag.put("backup", this.blockStateProvider);
} else {
final CompoundTag backupTag = updatedTag.getCompoundTag("backup");
updatedTag = backupTag != null ? backupTag : dummyBlockStateProvider();
}
}
return new BlockTransformData(updatedTag, sound, transformParticle, disallowedFaces, loot, dropStrategy, updateFromNeighbors, transformType, consumeOnUse, itemDamagePerUse);
}
private CompoundTag dummyBlockStateProvider() {
final CompoundTag state = new CompoundTag();
state.putString("Name", "dirt");
final CompoundTag tag = new CompoundTag();
tag.putString("type", "simple");
tag.put("state", state);
return tag;
}
@Override
public BlockTransformData copy() {
return new BlockTransformData(blockStateProvider.copy(), sound, transformParticle, disallowedFaces, loot, dropStrategy, updateFromNeighbors, transformType, consumeOnUse, itemDamagePerUse);
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.ResolvableFloat;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record BrewingFuel(ResolvableInt uses, ResolvableFloat speedMultiplier) {
public static final Type<BrewingFuel> TYPE = new Type<>(BrewingFuel.class) {
@Override
public BrewingFuel read(final ByteBuf buffer) {
final ResolvableInt uses = Types.RESOLVABLE_INT.read(buffer);
final ResolvableFloat speedMultiplier = Types.RESOLVABLE_FLOAT.read(buffer);
return new BrewingFuel(uses, speedMultiplier);
}
@Override
public void write(final ByteBuf buffer, final BrewingFuel value) {
Types.RESOLVABLE_INT.write(buffer, value.uses);
Types.RESOLVABLE_FLOAT.write(buffer, value.speedMultiplier);
}
@Override
public void write(final Ops ops, final BrewingFuel value) {
ops.writeMap(map -> map
.write("uses", Types.RESOLVABLE_INT, value.uses)
.write("speed_multiplier", Types.RESOLVABLE_FLOAT, value.speedMultiplier));
}
};
}
@@ -0,0 +1,40 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
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;
public record Compostable(ResolvableInt layers) {
public static final Type<Compostable> TYPE = new TransformingType<>(Types.RESOLVABLE_INT, Compostable.class, Compostable::new, Compostable::layers) {
@Override
public void write(final Ops ops, final Compostable value) {
ops.writeMap(map -> map.write("layers", Types.RESOLVABLE_INT, value.layers));
}
};
}
@@ -1,200 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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;
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.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
boolean hasConsumeParticles,
ConsumeEffect<?>[] consumeEffects) implements Copyable, Rewritable {
private static final HolderSetType REMOVE_EFFECTS_TYPE = new HolderSetType() {
@Override
public void write(final Ops ops, final HolderSet value) {
ops.writeMap(map -> map.write("effects", new HolderSetType(EnumTypes.MOB_EFFECT), value));
}
};
private static final Type<Float> TELEPORT_RANDOMLY_TYPE = new Type<>(Float.class) {
@Override
public void write(final ByteBuf buffer, final Float value) {
Types.FLOAT.writePrimitive(buffer, value);
}
@Override
public Float read(final ByteBuf buffer) {
return Types.FLOAT.readPrimitive(buffer);
}
@Override
public void write(final Ops ops, final Float value) {
ops.writeMap(map -> map.write("diameter", Types.FLOAT, 16F));
}
};
private static final HolderType<SoundEvent> PLAY_SOUND_TYPE = new HolderType<>(MappingData.MappingType.SOUND) {
@Override
public SoundEvent readDirect(final ByteBuf buffer) {
return Types.SOUND_EVENT.readDirect(buffer);
}
@Override
public void writeDirect(final ByteBuf buffer, final SoundEvent value) {
Types.SOUND_EVENT.writeDirect(buffer, value);
}
@Override
public void write(final Ops ops, final Holder<SoundEvent> value) {
ops.writeMap(map -> map.write("sound", Types.SOUND_EVENT, value));
}
};
public static final Type<?>[] EFFECT_TYPES = {
ApplyStatusEffects.TYPE,
REMOVE_EFFECTS_TYPE,
Types.EMPTY, // clear all effects
TELEPORT_RANDOMLY_TYPE,
PLAY_SOUND_TYPE
};
public static final Type<Consumable1_21_2> TYPE = new Type<>(Consumable1_21_2.class) {
@Override
public Consumable1_21_2 read(final ByteBuf buffer) {
final float consumeSeconds = buffer.readFloat();
final int animationType = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
final boolean hasConsumeParticles = buffer.readBoolean();
final ConsumeEffect<?>[] consumeEffects = ConsumeEffect.ARRAY_TYPE.read(buffer);
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, consumeEffects);
}
@Override
public void write(final ByteBuf buffer, final Consumable1_21_2 value) {
buffer.writeFloat(value.consumeSeconds);
Types.VAR_INT.writePrimitive(buffer, value.animationType);
Types.SOUND_EVENT.write(buffer, value.sound);
buffer.writeBoolean(value.hasConsumeParticles);
ConsumeEffect.ARRAY_TYPE.write(buffer, value.consumeEffects);
}
@Override
public void write(final Ops ops, final Consumable1_21_2 value) {
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "entity.generic.eat"));
ops.writeMap(map -> map
.writeOptional("consume_seconds", Types.FLOAT, value.consumeSeconds, 1.6F)
.writeOptional("animation", EnumTypes.ITEM_USE_ANIMATION, value.animationType, 1)
.writeOptional("sound", Types.SOUND_EVENT, value.sound, defaultSound)
.writeOptional("has_consume_particles", Types.BOOLEAN, value.hasConsumeParticles, true)
.writeOptional("consume_effects", ConsumeEffect.ARRAY_TYPE, value.consumeEffects, new ConsumeEffect<?>[0]));
}
};
public record ConsumeEffect<T>(int id, Type<T> type, T value) {
public static final Type<ConsumeEffect<?>> TYPE = new Type<>(ConsumeEffect.class) {
@Override
public ConsumeEffect<?> read(final ByteBuf buffer) {
// Oh no...
final int effectType = Types.VAR_INT.readPrimitive(buffer);
final Type<?> type = EFFECT_TYPES[effectType];
final Object value = type.read(buffer);
return ConsumeEffect.of(effectType, type, value);
}
@Override
public void write(final ByteBuf buffer, final ConsumeEffect<?> value) {
Types.VAR_INT.writePrimitive(buffer, value.id);
value.writeValue(buffer);
}
@Override
public void write(final Ops ops, final ConsumeEffect<?> value) {
writeGeneric(ops, value);
}
private <E> void writeGeneric(final Ops ops, final ConsumeEffect<E> value) {
ops.writeMap(map -> map
.write("type", EnumTypes.CONSUME_EFFECT, value.id)
.writeInlinedMap(value.type, value.value));
}
};
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE = new ArrayType<>(TYPE);
static <T> ConsumeEffect<T> of(final int id, final Type<T> type, final Object value) {
//noinspection unchecked
return new ConsumeEffect<>(id, type, (T) value);
}
void writeValue(final ByteBuf buf) {
this.type.write(buf, this.value);
}
}
public record ApplyStatusEffects(PotionEffect[] effects, float probability) {
public static final Type<ApplyStatusEffects> TYPE = new Type<>(ApplyStatusEffects.class) {
@Override
public ApplyStatusEffects read(final ByteBuf buffer) {
final PotionEffect[] effects = PotionEffect.ARRAY_TYPE.read(buffer);
final float probability = buffer.readFloat();
return new ApplyStatusEffects(effects, probability);
}
@Override
public void write(final ByteBuf buffer, final ApplyStatusEffects value) {
PotionEffect.ARRAY_TYPE.write(buffer, value.effects);
buffer.writeFloat(value.probability);
}
@Override
public void write(final Ops ops, final ApplyStatusEffects value) {
ops.writeMap(map -> map
.write("effects", PotionEffect.ARRAY_TYPE, value.effects)
.writeOptional("probability", Types.FLOAT, value.probability, 1F));
}
};
}
@Override
public Consumable1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundHolder = SoundEvent.rewriteHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundHolder == this.sound ? this : new Consumable1_21_2(consumeSeconds, animationType, soundHolder, hasConsumeParticles, consumeEffects);
}
@Override
public Consumable1_21_2 copy() {
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, Copyable.copy(consumeEffects));
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.ResolvableFloat;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record CookingFuel(ResolvableInt burnTime, ResolvableFloat speedMultiplier) {
public static final Type<CookingFuel> TYPE = new Type<>(CookingFuel.class) {
@Override
public CookingFuel read(final ByteBuf buffer) {
final ResolvableInt burnTime = Types.RESOLVABLE_INT.read(buffer);
final ResolvableFloat speedMultiplier = Types.RESOLVABLE_FLOAT.read(buffer);
return new CookingFuel(burnTime, speedMultiplier);
}
@Override
public void write(final ByteBuf buffer, final CookingFuel value) {
Types.RESOLVABLE_INT.write(buffer, value.burnTime);
Types.RESOLVABLE_FLOAT.write(buffer, value.speedMultiplier);
}
@Override
public void write(final Ops ops, final CookingFuel value) {
ops.writeMap(map -> map
.write("burn_time", Types.RESOLVABLE_INT, value.burnTime)
.write("speed_multiplier", Types.RESOLVABLE_FLOAT, value.speedMultiplier));
}
};
}
@@ -23,17 +23,23 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2.ConsumeEffect;
import com.viaversion.viaversion.api.minecraft.item.data.consumable.ConsumeEffect;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyable {
public static final Type<DeathProtection> TYPE = new TransformingType<>(ConsumeEffect.ARRAY_TYPE, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
public static final Type<DeathProtection> TYPE1_21_2 = new TransformingType<>(ConsumeEffect.ARRAY_TYPE1_21_2, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
@Override
public void write(final Ops ops, final DeathProtection value) {
ops.writeMap(map -> map.write("death_effects", ConsumeEffect.ARRAY_TYPE, value.deathEffects));
ops.writeMap(map -> map.write("death_effects", ConsumeEffect.ARRAY_TYPE1_21_2, value.deathEffects));
}
};
public static final Type<DeathProtection> TYPE26_3 = new TransformingType<>(ConsumeEffect.ARRAY_TYPE26_3, DeathProtection.class, DeathProtection::new, DeathProtection::deathEffects) {
@Override
public void write(final Ops ops, final DeathProtection value) {
ops.writeMap(map -> map.write("death_effects", ConsumeEffect.ARRAY_TYPE26_3, value.deathEffects));
}
};
@@ -38,12 +38,12 @@ public record DebugStickState(CompoundTag tag) implements Rewritable, Copyable {
@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) {
if (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 blockId == -1 || protocol.getMappingData().changedBlocks().contains(blockId);
});
}
return new DebugStickState(updatedTag);
@@ -46,8 +46,12 @@ public final class EnumTypes {
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");
public static final EnumType SWING_ANIMATION = new EnumType("none", "whack", "stab");
public static final EnumType SWING_ANIMATION1_21_11 = new EnumType("none", "whack", "stab");
public static final EnumType ITEM_USE_ANIMATION = new EnumType("none", "eat", "drink", "block", "bow", "trident", "crossbow", "spyglass", "toot_horn", "brush", "bundle", "spear");
public static final EnumType DIRECTION = new EnumType("down", "up", "north", "south", "west", "east");
public static final EnumType TRANSFORM_PARTICLE = new EnumType("none", "scrape", "wax_on", "wax_off");
public static final EnumType TRAMNSFORM_DROP_STRATEGY = new EnumType("clicked_face", "from_middle");
public static final EnumType TRAMNSFORM_TYPE = new EnumType("single_block", "copper_chest");
// 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"));
// Hardcoded registries
@@ -34,7 +34,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public final class FilterableComponent extends Filterable<Tag> implements Copyable, Rewritable {
public static final Type<FilterableComponent> TYPE = new FilterableType<>(Types.TAG, Types.OPTIONAL_TAG, FilterableComponent.class) {
public static final Type<FilterableComponent> TYPE = new FilterableType<>(Types.TEXT_COMPONENT_TAG, Types.OPTIONAL_TAG, FilterableComponent.class) {
@Override
protected FilterableComponent create(final Tag raw, final Tag filtered) {
return new FilterableComponent(raw, filtered);
@@ -37,9 +37,13 @@ import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range,
Tag description) implements Copyable, Rewritable {
int durabilityDamage, Tag description) implements Copyable, Rewritable {
public static final HolderType<Instrument1_21_2> TYPE = new HolderType<>() {
public Instrument1_21_2(final Holder<SoundEvent> soundEvent, final float useDuration, final float range, final Tag description) {
this(soundEvent, useDuration, range, 0, description);
}
public static final HolderType<Instrument1_21_2> TYPE1_21_2 = new HolderType<>() {
@Override
public Instrument1_21_2 readDirect(final ByteBuf buffer) {
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
@@ -71,16 +75,52 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
return ops.context().registryAccess().registryKey("instrument", id);
}
};
public static final EitherHolderType<Instrument1_21_2> EITHER_HOLDER_TYPE = new EitherHolderType<>(TYPE);
public static final EitherHolderType<Instrument1_21_2> EITHER_HOLDER_TYPE = new EitherHolderType<>(TYPE1_21_2);
public static final HolderType<Instrument1_21_2> TYPE26_3 = new HolderType<>() {
@Override
public Instrument1_21_2 readDirect(final ByteBuf buffer) {
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final float useDuration = Types.FLOAT.readPrimitive(buffer);
final float range = Types.FLOAT.readPrimitive(buffer);
final int durabilityDamage = Types.VAR_INT.readPrimitive(buffer);
final Tag description = Types.TAG.read(buffer);
return new Instrument1_21_2(soundEvent, useDuration, range, durabilityDamage, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final Instrument1_21_2 value) {
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.FLOAT.writePrimitive(buffer, value.useDuration());
Types.FLOAT.writePrimitive(buffer, value.range());
Types.VAR_INT.writePrimitive(buffer, value.durabilityDamage());
Types.TAG.write(buffer, value.description());
}
@Override
public void writeDirect(final Ops ops, final Instrument1_21_2 value) {
ops.writeMap(map -> map
.write("sound_event", Types.SOUND_EVENT, value.soundEvent())
.write("use_duration", Types.FLOAT, value.useDuration())
.write("range", Types.FLOAT, value.range())
.write("durability_damage", Types.VAR_INT, value.durabilityDamage())
.write("description", Types.TAG, value.description()));
}
@Override
protected Key identifier(final Ops ops, final int id) {
return ops.context().registryAccess().registryKey("instrument", id);
}
};
@Override
public Instrument1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = SoundEvent.rewriteHolder(this.soundEvent, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, description);
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, durabilityDamage, description);
}
@Override
public Instrument1_21_2 copy() {
return new Instrument1_21_2(soundEvent, useDuration, range, description.copy());
return new Instrument1_21_2(soundEvent, useDuration, range, durabilityDamage, description.copy());
}
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.data.MappingData;
import com.viaversion.viaversion.api.minecraft.HolderSet;
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.api.type.types.misc.HolderSetType;
import io.netty.buffer.ByteBuf;
public record MobVisibility(HolderSet targetingEntityTypes, float visibility) {
public static final Type<MobVisibility> TYPE = new Type<>(MobVisibility.class) {
@Override
public MobVisibility read(final ByteBuf buffer) {
final HolderSet targetingEntityTypes = Types.HOLDER_SET.read(buffer);
final float visibility = Types.FLOAT.readPrimitive(buffer);
return new MobVisibility(targetingEntityTypes, visibility);
}
@Override
public void write(final ByteBuf buffer, final MobVisibility value) {
Types.HOLDER_SET.write(buffer, value.targetingEntityTypes);
Types.FLOAT.writePrimitive(buffer, value.visibility);
}
@Override
public void write(final Ops ops, final MobVisibility value) {
ops.writeMap(map -> map
.write("targeting_entity_types", new HolderSetType(MappingData.MappingType.ENTITY_TYPE), value.targetingEntityTypes)
.write("visibility", Types.FLOAT, value.visibility));
}
};
}
@@ -31,11 +31,11 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
public record PotDecorations(int[] itemIds) implements Copyable, Rewritable {
public record PotDecorations1_20_5(int[] itemIds) implements Copyable, Rewritable {
public static final Type<PotDecorations> TYPE = new TransformingType<>(Types.VAR_INT_ARRAY_PRIMITIVE, PotDecorations.class, PotDecorations::new, PotDecorations::itemIds) {
public static final Type<PotDecorations1_20_5> TYPE = new TransformingType<>(Types.VAR_INT_ARRAY_PRIMITIVE, PotDecorations1_20_5.class, PotDecorations1_20_5::new, PotDecorations1_20_5::itemIds) {
@Override
public void write(final Ops ops, final PotDecorations value) {
public void write(final Ops ops, final PotDecorations1_20_5 value) {
ops.writeList(list -> {
for (final int itemId : value.itemIds) {
list.write(Types.IDENTIFIER, ops.context().registryAccess().item(itemId));
@@ -44,7 +44,7 @@ public record PotDecorations(int[] itemIds) implements Copyable, Rewritable {
}
};
public PotDecorations(final int backItem, final int leftItem, final int rightItem, final int frontItem) {
public PotDecorations1_20_5(final int backItem, final int leftItem, final int rightItem, final int frontItem) {
this(new int[]{backItem, leftItem, rightItem, frontItem});
}
@@ -69,16 +69,16 @@ public record PotDecorations(int[] itemIds) implements Copyable, Rewritable {
}
@Override
public PotDecorations rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
public PotDecorations1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final int[] newItems = new int[itemIds.length];
for (int i = 0; i < itemIds.length; i++) {
newItems[i] = Rewritable.rewriteItem(protocol, clientbound, itemIds[i]);
}
return new PotDecorations(newItems);
return new PotDecorations1_20_5(newItems);
}
@Override
public PotDecorations copy() {
return new PotDecorations(Copyable.copy(itemIds));
public PotDecorations1_20_5 copy() {
return new PotDecorations1_20_5(Copyable.copy(itemIds));
}
}
@@ -0,0 +1,96 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
import static com.viaversion.viaversion.util.Rewritable.rewriteItem;
public record PotDecorations26_3(@Nullable Item back, @Nullable Item left, @Nullable Item right,
@Nullable Item front) implements Copyable, Rewritable {
public static final class PotDecorationsType extends Type<PotDecorations26_3> {
private final Type<Item> itemTemplateType;
public PotDecorationsType(final Type<Item> itemTemplateType) {
super(PotDecorations26_3.class);
this.itemTemplateType = itemTemplateType;
}
@Override
public void write(final ByteBuf buffer, final PotDecorations26_3 value) {
itemTemplateType.write(buffer, value.back());
itemTemplateType.write(buffer, value.left());
itemTemplateType.write(buffer, value.right());
itemTemplateType.write(buffer, value.front());
}
@Override
public PotDecorations26_3 read(final ByteBuf buffer) {
final Item back = itemTemplateType.read(buffer);
final Item left = itemTemplateType.read(buffer);
final Item right = itemTemplateType.read(buffer);
final Item front = itemTemplateType.read(buffer);
return new PotDecorations26_3(back, left, right, front);
}
@Override
public void write(final Ops ops, final PotDecorations26_3 value) {
ops.writeMap(map -> map
.writeOptional("back", itemTemplateType, value.back())
.writeOptional("left", itemTemplateType, value.left())
.writeOptional("right", itemTemplateType, value.right())
.writeOptional("front", itemTemplateType, value.front())
);
}
}
@Override
public PotDecorations26_3 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new PotDecorations26_3(
rewriteItem(connection, protocol, clientbound, back),
rewriteItem(connection, protocol, clientbound, left),
rewriteItem(connection, protocol, clientbound, right),
rewriteItem(connection, protocol, clientbound, front)
);
}
@Override
public PotDecorations26_3 copy() {
return new PotDecorations26_3(
back == null ? null : back.copy(),
left == null ? null : left.copy(),
right == null ? null : right.copy(),
front == null ? null : front.copy()
);
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record SignText(Tag[] messages, Tag @Nullable [] filteredMessages, int color, boolean hasGlowingText) {
public static final Type<SignText> TYPE = new Type<>(SignText.class) {
@Override
public SignText read(final ByteBuf buffer) {
final Tag[] messages = Types.SIGN_TEXT.read(buffer);
final Tag[] filteredMessages = Types.OPTIONAL_SIGN_TEXT.read(buffer);
final int color = Types.VAR_INT.readPrimitive(buffer);
final boolean hasGlowingText = buffer.readBoolean();
return new SignText(messages, filteredMessages, color, hasGlowingText);
}
@Override
public void write(final ByteBuf buffer, final SignText value) {
Types.SIGN_TEXT.write(buffer, value.messages);
Types.OPTIONAL_SIGN_TEXT.write(buffer, value.filteredMessages);
Types.VAR_INT.writePrimitive(buffer, value.color);
Types.BOOLEAN.write(buffer, value.hasGlowingText);
}
@Override
public void write(final Ops ops, final SignText value) {
ops.writeMap(map -> map
.write("messages", Types.SIGN_TEXT, value.messages)
.writeOptional("filtered_messages", Types.SIGN_TEXT, value.filteredMessages)
.write("color", Types.VAR_INT, value.color, 15)
.write("has_glowing_text", Types.BOOLEAN, value.hasGlowingText, false));
}
};
}
@@ -29,9 +29,17 @@ import io.netty.buffer.ByteBuf;
public record SwingAnimation(int type, int duration) {
private static final int DEFAULT_TYPE = EnumTypes.SWING_ANIMATION.idFromName("whack");
public static final Type<SwingAnimation> TYPE = new SwingAnimationType(EnumTypes.SWING_ANIMATION1_21_11.idFromName("whack"));
private static class SwingAnimationType extends Type<SwingAnimation> {
private final int defaultType;
public SwingAnimationType(final int defaultType) {
super(SwingAnimation.class);
this.defaultType = defaultType;
}
public static final Type<SwingAnimation> TYPE = new Type<>(SwingAnimation.class) {
@Override
public SwingAnimation read(final ByteBuf buffer) {
final int type = Types.VAR_INT.readPrimitive(buffer);
@@ -48,9 +56,8 @@ public record SwingAnimation(int type, int duration) {
@Override
public void write(final Ops ops, final SwingAnimation value) {
ops.writeMap(map -> map
.writeOptional("type", EnumTypes.SWING_ANIMATION, value.type, DEFAULT_TYPE)
.writeOptional("duration", Types.INT, value.duration, 6)
);
.writeOptional("type", EnumTypes.SWING_ANIMATION1_21_11, value.type, this.defaultType)
.writeOptional("duration", Types.INT, value.duration, 6));
}
};
}
}
@@ -0,0 +1,39 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.TransformingType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
public record VillagerFood(int nutrition) {
public static final Type<VillagerFood> TYPE = new TransformingType<>(Types.VAR_INT, VillagerFood.class, VillagerFood::new, VillagerFood::nutrition) {
@Override
public void write(final Ops ops, final VillagerFood value) {
ops.writeMap(map -> map.write("nutrition", Types.VAR_INT, value.nutrition));
}
};
}
@@ -0,0 +1,54 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.data.PotionEffect;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record ApplyStatusEffects(PotionEffect[] effects, float probability) {
public static final Type<ApplyStatusEffects> TYPE = new Type<>(ApplyStatusEffects.class) {
@Override
public ApplyStatusEffects read(final ByteBuf buffer) {
final PotionEffect[] effects = PotionEffect.ARRAY_TYPE.read(buffer);
final float probability = buffer.readFloat();
return new ApplyStatusEffects(effects, probability);
}
@Override
public void write(final ByteBuf buffer, final ApplyStatusEffects value) {
PotionEffect.ARRAY_TYPE.write(buffer, value.effects);
buffer.writeFloat(value.probability);
}
@Override
public void write(final Ops ops, final ApplyStatusEffects value) {
ops.writeMap(map -> map
.write("effects", PotionEffect.ARRAY_TYPE, value.effects)
.writeOptional("probability", Types.FLOAT, value.probability, 1F));
}
};
}
@@ -0,0 +1,95 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
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.SoundEvent;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.minecraft.item.data.EnumTypes;
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.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
boolean hasConsumeParticles,
ConsumeEffect<?>[] consumeEffects) implements Copyable, Rewritable {
public static final Type<Consumable1_21_2> TYPE1_21_2 = new ConsumableType(ConsumeEffect.ARRAY_TYPE1_21_2);
public static final Type<Consumable1_21_2> TYPE26_3 = new ConsumableType(ConsumeEffect.ARRAY_TYPE26_3);
private static final class ConsumableType extends Type<Consumable1_21_2> {
private final Type<ConsumeEffect<?>[]> consumeEffectType;
private ConsumableType(final Type<ConsumeEffect<?>[]> consumeEffectType) {
super(Consumable1_21_2.class);
this.consumeEffectType = consumeEffectType;
}
@Override
public Consumable1_21_2 read(final ByteBuf buffer) {
final float consumeSeconds = buffer.readFloat();
final int animationType = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
final boolean hasConsumeParticles = buffer.readBoolean();
final ConsumeEffect<?>[] consumeEffects = consumeEffectType.read(buffer);
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, consumeEffects);
}
@Override
public void write(final ByteBuf buffer, final Consumable1_21_2 value) {
buffer.writeFloat(value.consumeSeconds);
Types.VAR_INT.writePrimitive(buffer, value.animationType);
Types.SOUND_EVENT.write(buffer, value.sound);
buffer.writeBoolean(value.hasConsumeParticles);
consumeEffectType.write(buffer, value.consumeEffects);
}
@Override
public void write(final Ops ops, final Consumable1_21_2 value) {
final Holder<SoundEvent> defaultSound = Holder.of(ops.context().registryAccess().id(MappingData.MappingType.SOUND, "entity.generic.eat"));
ops.writeMap(map -> map
.writeOptional("consume_seconds", Types.FLOAT, value.consumeSeconds, 1.6F)
.writeOptional("animation", EnumTypes.ITEM_USE_ANIMATION, value.animationType, 1)
.writeOptional("sound", Types.SOUND_EVENT, value.sound, defaultSound)
.writeOptional("has_consume_particles", Types.BOOLEAN, value.hasConsumeParticles, true)
.writeOptional("on_consume_effects", consumeEffectType, value.consumeEffects, new ConsumeEffect<?>[0]));
}
}
@Override
public Consumable1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundHolder = SoundEvent.rewriteHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundHolder == this.sound ? this : new Consumable1_21_2(consumeSeconds, animationType, soundHolder, hasConsumeParticles, consumeEffects);
}
@Override
public Consumable1_21_2 copy() {
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, Copyable.copy(consumeEffects));
}
}
@@ -0,0 +1,165 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
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.minecraft.item.data.EnumTypes;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
public record ConsumeEffect<T>(int id, Type<T> type, T value) {
private static final HolderSetType REMOVE_EFFECTS_TYPE = new HolderSetType() {
@Override
public void write(final Ops ops, final HolderSet value) {
ops.writeMap(map -> map.write("effects", new HolderSetType(EnumTypes.MOB_EFFECT), value));
}
};
public static final Type<Float> TELEPORT_RANDOMLY_TYPE1_21_2 = new Type<>(Float.class) {
@Override
public void write(final ByteBuf buffer, final Float value) {
Types.FLOAT.writePrimitive(buffer, value);
}
@Override
public Float read(final ByteBuf buffer) {
return Types.FLOAT.readPrimitive(buffer);
}
@Override
public void write(final Ops ops, final Float value) {
ops.writeMap(map -> map.write("diameter", Types.FLOAT, value, 16F));
}
};
public static final Type<TeleportRandomlyConsumeEffect> TELEPORT_RANDOMLY_TYPE26_3 = new Type<>(TeleportRandomlyConsumeEffect.class) {
@Override
public void write(final ByteBuf buffer, final TeleportRandomlyConsumeEffect value) {
Types.FLOAT.writePrimitive(buffer, value.diameter());
Types.BOOLEAN.write(buffer, value.directionalParticles());
}
@Override
public TeleportRandomlyConsumeEffect read(final ByteBuf buffer) {
final float diameter = Types.FLOAT.readPrimitive(buffer);
final boolean directionalParticles = Types.BOOLEAN.read(buffer);
return new TeleportRandomlyConsumeEffect(diameter, directionalParticles);
}
@Override
public void write(final Ops ops, final TeleportRandomlyConsumeEffect value) {
ops.writeMap(map -> map
.write("diameter", Types.FLOAT, value.diameter(), 16F)
.write("directional_particles", Types.BOOLEAN, value.directionalParticles(), true)
);
}
};
private static final HolderType<SoundEvent> PLAY_SOUND_TYPE = new HolderType<>(MappingData.MappingType.SOUND) {
@Override
public SoundEvent readDirect(final ByteBuf buffer) {
return Types.SOUND_EVENT.readDirect(buffer);
}
@Override
public void writeDirect(final ByteBuf buffer, final SoundEvent value) {
Types.SOUND_EVENT.writeDirect(buffer, value);
}
@Override
public void write(final Ops ops, final Holder<SoundEvent> value) {
ops.writeMap(map -> map.write("sound", Types.SOUND_EVENT, value));
}
};
public static final Type<?>[] EFFECT_TYPES1_21_2 = {
ApplyStatusEffects.TYPE,
REMOVE_EFFECTS_TYPE,
Types.EMPTY, // clear all effects
TELEPORT_RANDOMLY_TYPE1_21_2,
PLAY_SOUND_TYPE
};
public static final Type<?>[] EFFECT_TYPES26_3 = {
ApplyStatusEffects.TYPE,
REMOVE_EFFECTS_TYPE,
Types.EMPTY, // clear all effects
TELEPORT_RANDOMLY_TYPE26_3,
PLAY_SOUND_TYPE
};
public static final Type<ConsumeEffect<?>> TYPE1_21_2 = new ConsumeEffectType(EFFECT_TYPES1_21_2);
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE1_21_2 = new ArrayType<>(TYPE1_21_2);
public static final Type<ConsumeEffect<?>> TYPE26_3 = new ConsumeEffectType(EFFECT_TYPES26_3);
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE26_3 = new ArrayType<>(TYPE26_3);
static <T> ConsumeEffect<T> of(final int id, final Type<T> type, final Object value) {
//noinspection unchecked
return new ConsumeEffect<>(id, type, (T) value);
}
void writeValue(final ByteBuf buf) {
this.type.write(buf, this.value);
}
private static final class ConsumeEffectType extends Type<ConsumeEffect<?>> {
private final Type<?>[] types;
private ConsumeEffectType(final Type<?>[] types) {
super(ConsumeEffect.class);
this.types = types;
}
@Override
public ConsumeEffect<?> read(final ByteBuf buffer) {
// Oh no...
final int effectType = Types.VAR_INT.readPrimitive(buffer);
final Type<?> type = types[effectType];
final Object value = type.read(buffer);
return ConsumeEffect.of(effectType, type, value);
}
@Override
public void write(final ByteBuf buffer, final ConsumeEffect<?> value) {
Types.VAR_INT.writePrimitive(buffer, value.id);
value.writeValue(buffer);
}
@Override
public void write(final Ops ops, final ConsumeEffect<?> value) {
writeGeneric(ops, value);
}
private <E> void writeGeneric(final Ops ops, final ConsumeEffect<E> value) {
ops.writeMap(map -> map
.write("type", EnumTypes.CONSUME_EFFECT, value.id)
.writeInlinedMap(value.type, value.value));
}
}
}
@@ -0,0 +1,26 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.consumable;
public record TeleportRandomlyConsumeEffect(float diameter, boolean directionalParticles) {
}
@@ -20,7 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
@@ -30,86 +30,86 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern,
boolean showInTooltip) implements Rewritable {
public record ArmorTrim1_20_5(Holder<ArmorTrimMaterial1_20_5> material, Holder<ArmorTrimPattern> pattern,
boolean showInTooltip) implements Rewritable {
public ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern) {
public ArmorTrim1_20_5(Holder<ArmorTrimMaterial1_20_5> material, Holder<ArmorTrimPattern> pattern) {
this(material, pattern, true);
}
public static final Type<ArmorTrim> TYPE1_20_5 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_20_5 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_20_5.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_20_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_20_5.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_20_5.write(buffer, value.material);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_2 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_21_2 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_2.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_21_2.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_2.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_21_2.write(buffer, value.material);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_4 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_21_4 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_4.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_21_4.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_4.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_21_4.write(buffer, value.material);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_5 = new Type<>(ArmorTrim.class) {
public static final Type<ArmorTrim1_20_5> TYPE1_21_5 = new Type<>(ArmorTrim1_20_5.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_5.read(buffer);
public ArmorTrim1_20_5 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial1_20_5> material = ArmorTrimMaterial1_20_5.TYPE1_21_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_21_5.read(buffer);
return new ArmorTrim(material, pattern);
return new ArmorTrim1_20_5(material, pattern);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_5.write(buffer, value.material);
public void write(final ByteBuf buffer, final ArmorTrim1_20_5 value) {
ArmorTrimMaterial1_20_5.TYPE1_21_5.write(buffer, value.material);
ArmorTrimPattern.TYPE1_21_5.write(buffer, value.pattern);
}
@Override
public void write(final Ops ops, final ArmorTrim value) {
public void write(final Ops ops, final ArmorTrim1_20_5 value) {
ops.writeMap(map -> map
.write("material", ArmorTrimMaterial.TYPE1_21_5, value.material)
.write("material", ArmorTrimMaterial1_20_5.TYPE1_21_5, value.material)
.write("pattern", ArmorTrimPattern.TYPE1_21_5, value.pattern));
}
};
@Override
public ArmorTrim rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimMaterial> material = this.material;
public ArmorTrim1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimMaterial1_20_5> material = this.material;
if (material.isDirect()) {
material = Holder.of(material.value().rewrite(connection, protocol, clientbound));
}
@@ -118,6 +118,6 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
if (pattern.isDirect()) {
pattern = Holder.of(pattern.value().rewrite(connection, protocol, clientbound));
}
return new ArmorTrim(material, pattern, showInTooltip);
return new ArmorTrim1_20_5(material, pattern, showInTooltip);
}
}
@@ -0,0 +1,66 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.trim;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
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.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ArmorTrim26_3(Holder<ArmorTrimMaterial26_3> material,
Holder<ArmorTrimPattern> pattern) implements Rewritable {
public static final Type<ArmorTrim26_3> TYPE = new Type<>(ArmorTrim26_3.class) {
@Override
public ArmorTrim26_3 read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial26_3> material = ArmorTrimMaterial26_3.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_21_5.read(buffer);
return new ArmorTrim26_3(material, pattern);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim26_3 value) {
ArmorTrimMaterial26_3.TYPE.write(buffer, value.material);
ArmorTrimPattern.TYPE1_21_5.write(buffer, value.pattern);
}
@Override
public void write(final Ops ops, final ArmorTrim26_3 value) {
ops.writeMap(map -> map
.write("material", ArmorTrimMaterial26_3.TYPE, value.material)
.write("pattern", ArmorTrimPattern.TYPE1_21_5, value.pattern));
}
};
@Override
public ArmorTrim26_3 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimPattern> pattern = this.pattern;
if (pattern.isDirect()) {
pattern = Holder.of(pattern.value().rewrite(connection, protocol, clientbound));
}
return new ArmorTrim26_3(material, pattern);
}
}
@@ -20,7 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -35,23 +35,23 @@ import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import java.util.Map;
public record ArmorTrimMaterial(String assetName, int itemId, float itemModelIndex,
Map<String, String> overrideArmorMaterials,
Tag description) implements Copyable, Rewritable {
public record ArmorTrimMaterial1_20_5(String assetName, int itemId, float itemModelIndex,
Map<String, String> overrideArmorMaterials,
Tag description) implements Copyable, Rewritable {
public ArmorTrimMaterial(final String assetName, final int itemId, final Map<String, String> overrideArmorMaterials, final Tag description) {
public ArmorTrimMaterial1_20_5(final String assetName, final int itemId, final Map<String, String> overrideArmorMaterials, final Tag description) {
this(assetName, itemId, 0F, overrideArmorMaterials, description);
}
public ArmorTrimMaterial(final String assetName, final Map<String, String> overrideArmorMaterials, final Tag description) {
public ArmorTrimMaterial1_20_5(final String assetName, final Map<String, String> overrideArmorMaterials, final Tag description) {
this(assetName, 0, 0F, overrideArmorMaterials, description);
}
public static final HolderType<ArmorTrimMaterial> TYPE1_20_5 = new HolderType<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> TYPE1_20_5 = new HolderType<>() {
// The override key is an int, but given we don't use it at all and that creating a new type is annoying,
// we'll just store it in the string map:tm:
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
final float itemModelIndex = buffer.readFloat();
@@ -65,11 +65,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, itemModelIndex, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, item, itemModelIndex, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
buffer.writeFloat(value.itemModelIndex());
@@ -83,9 +83,9 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_2 = new HolderType<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> TYPE1_21_2 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
final float itemModelIndex = buffer.readFloat();
@@ -99,11 +99,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, itemModelIndex, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, item, itemModelIndex, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
buffer.writeFloat(value.itemModelIndex());
@@ -117,9 +117,9 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_4 = new HolderType<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> TYPE1_21_4 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int item = Types.VAR_INT.readPrimitive(buffer);
@@ -132,11 +132,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, item, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, item, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.itemId());
@@ -149,9 +149,9 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
Types.TAG.write(buffer, value.description());
}
};
public static final HolderType<ArmorTrimMaterial> TYPE1_21_5 = new HolderType<>() {
public static final HolderType<ArmorTrimMaterial1_20_5> TYPE1_21_5 = new HolderType<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
public ArmorTrimMaterial1_20_5 readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
@@ -163,11 +163,11 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, overrideArmorMaterials, description);
return new ArmorTrimMaterial1_20_5(assetName, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial1_20_5 value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
@@ -180,7 +180,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
@Override
public void writeDirect(final Ops ops, final ArmorTrimMaterial object) {
public void writeDirect(final Ops ops, final ArmorTrimMaterial1_20_5 object) {
ops.writeMap(map -> {
map.write("asset_name", Types.STRING, object.assetName());
if (!object.overrideArmorMaterials.isEmpty()) {
@@ -201,12 +201,12 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
};
@Override
public ArmorTrimMaterial rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new ArmorTrimMaterial(assetName, Rewritable.rewriteItem(protocol, clientbound, itemId), itemModelIndex, overrideArmorMaterials, description);
public ArmorTrimMaterial1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new ArmorTrimMaterial1_20_5(assetName, Rewritable.rewriteItem(protocol, clientbound, itemId), itemModelIndex, overrideArmorMaterials, description);
}
@Override
public ArmorTrimMaterial copy() {
return new ArmorTrimMaterial(assetName, itemId, itemModelIndex, new Object2ObjectArrayMap<>(overrideArmorMaterials), description);
public ArmorTrimMaterial1_20_5 copy() {
return new ArmorTrimMaterial1_20_5(assetName, itemId, itemModelIndex, new Object2ObjectArrayMap<>(overrideArmorMaterials), description);
}
}
@@ -0,0 +1,61 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.trim;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
public record ArmorTrimMaterial26_3(String paletteId, Tag description) {
public static final HolderType<ArmorTrimMaterial26_3> TYPE = new HolderType<>() {
@Override
public ArmorTrimMaterial26_3 readDirect(final ByteBuf buffer) {
final String paletteId = Types.STRING.read(buffer);
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial26_3(paletteId, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial26_3 value) {
Types.STRING.write(buffer, value.paletteId());
Types.TAG.write(buffer, value.description());
}
@Override
public void writeDirect(final Ops ops, final ArmorTrimMaterial26_3 object) {
ops.writeMap(map -> {
map.write("palette_id", Types.IDENTIFIER, Key.of(object.paletteId()));
map.write("description", Types.TEXT_COMPONENT_TAG, object.description());
});
}
@Override
protected Key identifier(final Ops ops, final int id) {
return ops.context().registryAccess().registryKey("trim_material", id);
}
};
}
@@ -20,7 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
@@ -20,7 +20,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
package com.viaversion.viaversion.api.minecraft.item.data.trim;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
@@ -32,34 +32,34 @@ import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
public record ProvidesTrimMaterial(EitherHolder<ArmorTrimMaterial> material) implements Rewritable {
public record ProvidesTrimMaterial1_20_5(EitherHolder<ArmorTrimMaterial1_20_5> material) implements Rewritable {
public static final Type<ProvidesTrimMaterial> TYPE = new Type<>(ProvidesTrimMaterial.class) {
public static final Type<ProvidesTrimMaterial1_20_5> TYPE = new Type<>(ProvidesTrimMaterial1_20_5.class) {
@Override
public ProvidesTrimMaterial read(final ByteBuf buffer) {
final EitherHolder<ArmorTrimMaterial> position = EitherHolderType.read(buffer, ArmorTrimMaterial.TYPE1_21_5);
return new ProvidesTrimMaterial(position);
public ProvidesTrimMaterial1_20_5 read(final ByteBuf buffer) {
final EitherHolder<ArmorTrimMaterial1_20_5> position = EitherHolderType.read(buffer, ArmorTrimMaterial1_20_5.TYPE1_21_5);
return new ProvidesTrimMaterial1_20_5(position);
}
@Override
public void write(final ByteBuf buffer, final ProvidesTrimMaterial value) {
EitherHolderType.write(buffer, value.material, ArmorTrimMaterial.TYPE1_21_5);
public void write(final ByteBuf buffer, final ProvidesTrimMaterial1_20_5 value) {
EitherHolderType.write(buffer, value.material, ArmorTrimMaterial1_20_5.TYPE1_21_5);
}
@Override
public void write(final Ops ops, final ProvidesTrimMaterial value) {
EitherHolderType.write(ops, value.material, ArmorTrimMaterial.TYPE1_21_5);
public void write(final Ops ops, final ProvidesTrimMaterial1_20_5 value) {
EitherHolderType.write(ops, value.material, ArmorTrimMaterial1_20_5.TYPE1_21_5);
}
};
@Override
public ProvidesTrimMaterial rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
public ProvidesTrimMaterial1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (material.hasKey() || material.holder().hasId()) {
return this;
}
final ArmorTrimMaterial trimMaterial = material.holder().value();
return new ProvidesTrimMaterial(EitherHolder.of(Holder.of(trimMaterial.rewrite(connection, protocol, clientbound))));
final ArmorTrimMaterial1_20_5 trimMaterial = material.holder().value();
return new ProvidesTrimMaterial1_20_5(EitherHolder.of(Holder.of(trimMaterial.rewrite(connection, protocol, clientbound))));
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.protocol;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.connection.ProtocolStorables;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.platform.providers.ViaProviders;
@@ -33,6 +34,7 @@ import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.State;
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.ComponentRewriter;
import com.viaversion.viaversion.api.rewriter.EntityRewriter;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
@@ -58,6 +60,22 @@ import org.checkerframework.checker.nullness.qual.Nullable;
*/
public interface Protocol<CU extends ClientboundPacketType, CM extends ClientboundPacketType, SM extends ServerboundPacketType, SU extends ServerboundPacketType> {
/**
* Returns the server protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the server protocol version
*/
@Nullable ProtocolVersion getServerVersion();
/**
* Returns the client protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the client protocol version for this protocol
*/
@Nullable ProtocolVersion getClientVersion();
default void registerClientbound(State state, ClientboundPacketType packetType, @Nullable PacketHandler handler) {
Preconditions.checkArgument(packetType.state() == state);
registerClientbound(state, packetType.getId(), packetType.getId(), handler, false);
@@ -460,6 +478,15 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
return false;
}
/**
* Returns the index assigned to this protocol during registration.
*
* @return protocol index, or -1 if not yet registered
*/
int index();
ProtocolStorables createStorables();
/**
* Marks this protocol as dependent on another. Before being initialized, it will wait for the dependency's completion.
*
@@ -318,4 +318,12 @@ public interface ProtocolManager {
* @return whether the mappings have been loaded
*/
boolean hasLoadedMappings();
/**
* Returns the number of registered protocols.
* Used to size per-connection protocol data arrays.
*
* @return number of registered protocols
*/
int registeredProtocolCount();
}
@@ -28,5 +28,11 @@ public enum State {
STATUS,
LOGIN,
CONFIGURATION,
PLAY
PLAY;
private static final int STATES_COUNT = values().length;
public static int statesCount() {
return STATES_COUNT;
}
}
@@ -27,7 +27,7 @@ import java.util.Arrays;
import org.checkerframework.checker.nullness.qual.Nullable;
final class PacketArrayMappings implements PacketMappings {
private final PacketMapping[][] packets = new PacketMapping[State.values().length][];
private final PacketMapping[][] packets = new PacketMapping[State.statesCount()][];
@Override
public @Nullable PacketMapping mappedPacket(final State state, final int unmappedId) {
@@ -95,6 +95,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_21_11 = register(774, "1.21.11");
public static final ProtocolVersion v26_1 = register(775, "26.1-26.1.2", new SubVersionRange("26.1", 0, 2));
public static final ProtocolVersion v26_2 = register(776, "26.2");
public static final ProtocolVersion v26_3 = register(777, "26.3");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -87,6 +87,6 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
* @return entity tracker
*/
default <E extends EntityTracker> E tracker(UserConnection connection) {
return connection.getEntityTracker(protocol().getClass());
return connection.getEntityTracker(protocol());
}
}
@@ -36,6 +36,8 @@ public interface RegistryDataRewriter {
void updateDialog(UserConnection connection, CompoundTag tag);
boolean updateBlockStateProvider(CompoundTag tag);
/**
* Sends registries that had additional entries configured, but weren't sent by the server at all
* by the time finish_configuration was sent to the client.
@@ -36,6 +36,8 @@ import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature;
import com.viaversion.viaversion.api.minecraft.ProfileKey;
import com.viaversion.viaversion.api.minecraft.Quaternion;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
import com.viaversion.viaversion.api.minecraft.ResolvableFloat;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
import com.viaversion.viaversion.api.minecraft.ResolvableProfile;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.minecraft.Vector;
@@ -58,6 +60,7 @@ import com.viaversion.viaversion.api.type.types.ByteType;
import com.viaversion.viaversion.api.type.types.ComponentType;
import com.viaversion.viaversion.api.type.types.DoubleType;
import com.viaversion.viaversion.api.type.types.EmptyType;
import com.viaversion.viaversion.api.type.types.FixedLengthArrayType;
import com.viaversion.viaversion.api.type.types.FloatArrayType;
import com.viaversion.viaversion.api.type.types.FloatType;
import com.viaversion.viaversion.api.type.types.IntArrayType;
@@ -105,6 +108,7 @@ import com.viaversion.viaversion.api.type.types.math.EulerAngleType;
import com.viaversion.viaversion.api.type.types.math.GlobalBlockPositionType;
import com.viaversion.viaversion.api.type.types.math.LowPrecisionVectorType;
import com.viaversion.viaversion.api.type.types.math.QuaternionType;
import com.viaversion.viaversion.api.type.types.math.Vector3dType;
import com.viaversion.viaversion.api.type.types.math.Vector3fType;
import com.viaversion.viaversion.api.type.types.math.VectorType;
import com.viaversion.viaversion.api.type.types.misc.CompoundTagHolderType;
@@ -118,6 +122,8 @@ import com.viaversion.viaversion.api.type.types.misc.NamedCompoundTagType;
import com.viaversion.viaversion.api.type.types.misc.PlayerMessageSignatureType;
import com.viaversion.viaversion.api.type.types.misc.ProfileKeyType;
import com.viaversion.viaversion.api.type.types.misc.ProfilePropertyType;
import com.viaversion.viaversion.api.type.types.misc.ResolvableFloatType;
import com.viaversion.viaversion.api.type.types.misc.ResolvableIntType;
import com.viaversion.viaversion.api.type.types.misc.ResolvableProfileType;
import com.viaversion.viaversion.api.type.types.misc.SoundEventType;
import com.viaversion.viaversion.api.type.types.misc.TagKeyType;
@@ -184,6 +190,8 @@ public final class Types {
public static final Type<int[]> VAR_INT_ARRAY_PRIMITIVE = new VarIntArrayType();
public static final VarLongType VAR_LONG = new VarLongType();
public static final BitSetType BIT_SET = new BitSetType(); // Generic length
/* MC Types */
public static final Type<byte[]> SERVERBOUND_CUSTOM_PAYLOAD_DATA = new RemainingBytesType(Short.MAX_VALUE);
@@ -192,6 +200,9 @@ public final class Types {
public static final Type<Key[]> IDENTIFIER_ARRAY = new ArrayType<>(IDENTIFIER);
public static final Type<Key> TAG_KEY = new TagKeyType();
public static final Type<ResolvableFloat> RESOLVABLE_FLOAT = new ResolvableFloatType();
public static final Type<ResolvableInt> RESOLVABLE_INT = new ResolvableIntType();
public static final Type<BlockPosition> BLOCK_POSITION1_8 = new BlockPositionType1_8();
public static final Type<BlockPosition> OPTIONAL_POSITION1_8 = new BlockPositionType1_8.OptionalBlockPositionType();
public static final Type<BlockPosition> BLOCK_POSITION1_14 = new BlockPositionType1_14();
@@ -199,6 +210,7 @@ public final class Types {
public static final Type<EulerAngle> ROTATIONS = new EulerAngleType();
public static final Type<Vector> VECTOR = new VectorType();
public static final Type<Vector3f> VECTOR3F = new Vector3fType();
public static final Type<Vector3d> VECTOR3D = new Vector3dType();
public static final Type<Quaternion> QUATERNION = new QuaternionType();
public static final Type<Vector3d> LOW_PRECISION_VECTOR = new LowPrecisionVectorType();
@Deprecated(forRemoval = true)
@@ -215,7 +227,10 @@ public final class Types {
public static final Type<Tag[]> TAG_ARRAY = new ArrayType<>(TAG);
public static final Type<Tag> OPTIONAL_TAG = TagType.OptionalTagType.type();
public static final Type<Tag> TEXT_COMPONENT_TAG = new TextComponentTagType(); // only strictly needed for hashing
public static final Type<Tag> CUSTOM_CLICK_ACTION_TAG = new LengthPrefixedTagType(65536);
public static final FixedLengthArrayType<Tag> SIGN_TEXT = new FixedLengthArrayType<>(TAG, 4);
public static final Type<Tag[]> OPTIONAL_SIGN_TEXT = SIGN_TEXT.new OptionalFixedLengthArrayType();
public static final Type<Tag> TRUSTED_TAG = new TagType(false);
public static final Type<Tag> TRUSTED_OPTIONAL_TAG = TagType.OptionalTagType.trustedType();
@@ -280,6 +295,7 @@ public final class Types {
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_9 = new EntityDataListType(ENTITY_DATA1_9);
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_12 = new EntityDataListType(ENTITY_DATA1_12);
// No longer used past 1.20.2
public static final Type<Item> ITEM1_8 = new ItemType1_8();
public static final Type<Item> ITEM1_13 = new ItemType1_13();
@@ -31,7 +31,7 @@ import java.util.ArrayList;
import java.util.List;
public class ArrayType<T> extends Type<T[]> {
private final Type<T> elementType;
protected final Type<T> elementType;
private final int maxLength;
public ArrayType(Type<T> type) {
@@ -66,7 +66,7 @@ public class ArrayType<T> extends Type<T[]> {
return amount < Short.MAX_VALUE ? readArray(buffer, amount) : readList(buffer, amount);
}
private T[] readArray(ByteBuf buffer, int length) {
protected T[] readArray(ByteBuf buffer, int length) {
T[] array = createArray(length);
for (int i = 0; i < length; i++) {
array[i] = elementType.read(buffer);
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.type.types;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.util.Arrays;
import java.util.BitSet;
@@ -39,17 +40,31 @@ public class BitSetType extends Type<BitSet> {
this.bytesLength = (int) Math.ceil(length / 8D);
}
public BitSetType() {
super(BitSet.class);
this.length = -1;
this.bytesLength = -1;
}
@Override
public BitSet read(ByteBuf buffer) {
final byte[] bytes = new byte[bytesLength];
buffer.readBytes(bytes);
return BitSet.valueOf(bytes);
if (this.length != -1) {
final byte[] bytes = new byte[bytesLength];
buffer.readBytes(bytes);
return BitSet.valueOf(bytes);
} else {
return BitSet.valueOf(Types.BYTE_ARRAY_PRIMITIVE.read(buffer));
}
}
@Override
public void write(ByteBuf buffer, BitSet object) {
Preconditions.checkArgument(object.length() <= length, "BitSet of length %s larger than max length %s", object.length(), length);
final byte[] bytes = object.toByteArray();
buffer.writeBytes(bytes.length == bytesLength ? bytes : Arrays.copyOf(bytes, bytesLength));
if (this.length != -1) {
Preconditions.checkArgument(object.length() <= length, "BitSet of length %s larger than max length %s", object.length(), length);
final byte[] bytes = object.toByteArray();
buffer.writeBytes(bytes.length == bytesLength ? bytes : Arrays.copyOf(bytes, bytesLength));
} else {
Types.BYTE_ARRAY_PRIMITIVE.write(buffer, object.toByteArray());
}
}
}
@@ -76,4 +76,16 @@ public final class EnumType extends VarIntType {
public enum Fallback {
ZERO, WRAP, CLAMP
}
public final class EnumArrayType extends VarIntArrayType {
@Override
public void write(final Ops ops, final int[] value) {
ops.writeList(list -> {
for (final int ordinal : value) {
list.write(Types.STRING, nameFromId(ordinal));
}
});
}
}
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class FixedLengthArrayType<T> extends ArrayType<T> {
private final int length;
public FixedLengthArrayType(final Type<T> type, final int length) {
super(type);
this.length = length;
}
@Override
public T[] read(final ByteBuf buffer) {
return readArray(buffer, this.length);
}
@Override
public void write(final ByteBuf buffer, final T[] object) {
for (final T o : object) {
elementType.write(buffer, o);
}
}
public final class OptionalFixedLengthArrayType extends OptionalType<T[]> {
public OptionalFixedLengthArrayType() {
super(FixedLengthArrayType.this);
}
}
}
@@ -34,7 +34,6 @@ import io.netty.buffer.ByteBuf;
// Very similar to normal items (and just results in an item), except it allows non-positive amounts and has id/amount swapped because ???
public final class ItemCostType1_20_5 extends Type<Item> {
private static final StructuredData<?>[] EMPTY_DATA_ARRAY = new StructuredData[0];
private final Type<StructuredData<?>[]> dataArrayType;
public ItemCostType1_20_5(final Type<StructuredData<?>[]> dataArrayType) {
@@ -54,7 +53,8 @@ public final class ItemCostType1_20_5 extends Type<Item> {
public void write(final ByteBuf buffer, final Item object) {
Types.VAR_INT.writePrimitive(buffer, object.identifier());
Types.VAR_INT.writePrimitive(buffer, object.amount());
dataArrayType.write(buffer, object.dataContainer().data().values().toArray(EMPTY_DATA_ARRAY));
// Item costs are exact-match predicates without removal markers, so empty data can't be written
dataArrayType.write(buffer, object.dataContainer().data().values().stream().filter(StructuredData::isPresent).toArray(StructuredData[]::new));
}
public static final class OptionalItemCostType extends OptionalType<Item> {
@@ -0,0 +1,49 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.math;
import com.viaversion.viaversion.api.minecraft.Vector3d;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public class Vector3dType extends Type<Vector3d> {
public Vector3dType() {
super(Vector3d.class);
}
@Override
public Vector3d read(final ByteBuf buffer) {
final double x = buffer.readDouble();
final double y = buffer.readDouble();
final double z = buffer.readDouble();
return new Vector3d(x, y, z);
}
@Override
public void write(final ByteBuf buffer, final Vector3d object) {
buffer.writeDouble(object.x());
buffer.writeDouble(object.y());
buffer.writeDouble(object.z());
}
}
@@ -31,6 +31,10 @@ import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.io.FastByteBufInputStream;
import com.viaversion.viaversion.io.FastByteBufOutputStream;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -72,7 +76,8 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
}
final TagLimiter tagLimiter = TagLimiter.create(maxBytes, TagLimiter.DEFAULT_MAX_NESTING_LEVEL);
return CompoundTag.read(new FastByteBufInputStream(buffer), tagLimiter, 0);
final DataInput in = TagType.USE_JAVA_DATA_IO ? new ByteBufInputStream(buffer) : new FastByteBufInputStream(buffer);
return CompoundTag.read(in, tagLimiter, 0);
}
public static void write(final ByteBuf buffer, final Tag tag, final @Nullable String name) throws IOException {
@@ -81,7 +86,7 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
return;
}
final FastByteBufOutputStream out = new FastByteBufOutputStream(buffer);
final DataOutput out = TagType.USE_JAVA_DATA_IO ? new ByteBufOutputStream(buffer) : new FastByteBufOutputStream(buffer);
out.writeByte(tag.getTagId());
if (name != null) {
out.writeUTF(name);
@@ -0,0 +1,66 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.misc;
import com.viaversion.viaversion.api.minecraft.ResolvableFloat;
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;
public final class ResolvableFloatType extends Type<ResolvableFloat> {
public ResolvableFloatType() {
super(ResolvableFloat.class);
}
@Override
public ResolvableFloat read(final ByteBuf buffer) {
if (buffer.readBoolean()) {
return ResolvableFloat.of(Types.FLOAT.readPrimitive(buffer));
} else {
return ResolvableFloat.of(Types.STRING.read(buffer));
}
}
@Override
public void write(final ByteBuf buffer, final ResolvableFloat value) {
if (value.isLeft()) {
buffer.writeBoolean(true);
Types.FLOAT.writePrimitive(buffer, value.left());
} else {
buffer.writeBoolean(false);
Types.IDENTIFIER.write(buffer, Key.of(value.right()));
}
}
@Override
public void write(final Ops ops, final ResolvableFloat value) {
if (value.isLeft()) {
Types.FLOAT.write(ops, value.left());
} else {
Types.IDENTIFIER.write(ops, Key.of(value.right()));
}
}
}
@@ -0,0 +1,66 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.misc;
import com.viaversion.viaversion.api.minecraft.ResolvableInt;
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;
public final class ResolvableIntType extends Type<ResolvableInt> {
public ResolvableIntType() {
super(ResolvableInt.class);
}
@Override
public ResolvableInt read(final ByteBuf buffer) {
if (buffer.readBoolean()) {
return ResolvableInt.of(Types.INT.readPrimitive(buffer));
} else {
return ResolvableInt.of(Types.STRING.read(buffer));
}
}
@Override
public void write(final ByteBuf buffer, final ResolvableInt value) {
if (value.isLeft()) {
buffer.writeBoolean(true);
Types.INT.writePrimitive(buffer, value.left());
} else {
buffer.writeBoolean(false);
Types.IDENTIFIER.write(buffer, Key.of(value.right()));
}
}
@Override
public void write(final Ops ops, final ResolvableInt value) {
if (value.isLeft()) {
Types.INT.write(ops, value.left());
} else {
Types.IDENTIFIER.write(ops, Key.of(value.right()));
}
}
}
@@ -45,11 +45,14 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.io.FastByteBufInputStream;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufInputStream;
import java.io.DataInput;
import java.io.IOException;
import java.util.Map;
public class TagType extends Type<Tag> {
static final boolean USE_JAVA_DATA_IO = Runtime.version().feature() >= 24; // Improved by a lot in JDK 24
private final int maxBytes;
public TagType() {
@@ -70,7 +73,8 @@ public class TagType extends Type<Tag> {
final TagLimiter tagLimiter = TagLimiter.create(this.maxBytes, TagLimiter.DEFAULT_MAX_NESTING_LEVEL);
try {
return TagRegistry.read(id, new FastByteBufInputStream(buffer), tagLimiter, 0);
final DataInput in = USE_JAVA_DATA_IO ? new ByteBufInputStream(buffer) : new FastByteBufInputStream(buffer);
return TagRegistry.read(id, in, tagLimiter, 0);
} catch (final IOException e) {
if (Via.getManager().isDebug()) {
throw new RuntimeException(e);
@@ -27,6 +27,7 @@ import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_2;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_5;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys26_2;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys26_3;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_20_5;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_11;
@@ -34,6 +35,7 @@ import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_9;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_3;
/**
* Holds versioned accessors for highly volatile types, specifically around items and data components.
@@ -53,4 +55,5 @@ public final class VersionedTypes {
public static final Types1_20_5<StructuredDataKeys1_21_11, EntityDataTypes1_21_11> V1_21_11 = new Types1_20_5<>(StructuredDataKeys1_21_11::new, EntityDataTypes1_21_11::new);
public static final Types26_1<StructuredDataKeys1_21_11, EntityDataTypes26_1> V26_1 = new Types26_1<>(StructuredDataKeys1_21_11::new, EntityDataTypes26_1::new);
public static final Types26_1<StructuredDataKeys26_2, EntityDataTypes26_1> V26_2 = new Types26_1<>(StructuredDataKeys26_2::new, EntityDataTypes26_1::new);
public static final Types26_1<StructuredDataKeys26_3, EntityDataTypes26_3> V26_3 = new Types26_1<>(StructuredDataKeys26_3::new, EntityDataTypes26_3::new);
}
@@ -29,11 +29,11 @@ public class EitherImpl<X, Y> implements Either<X, Y> {
private final X left;
private final Y right;
protected EitherImpl(final X left, final Y value) {
protected EitherImpl(final X left, final Y right) {
this.left = left;
this.right = value;
Preconditions.checkArgument(left == null || value == null, "Either.left and Either.right are both present");
Preconditions.checkArgument(left != null || value != null, "Either.left and Either.right are both null");
this.right = right;
Preconditions.checkArgument(left == null || right == null, "Either.left and Either.right are both present");
Preconditions.checkArgument(left != null || right != null, "Either.left and Either.right are both null");
}
@Override
@@ -71,6 +71,7 @@ public final class EntityTypeUtil {
final int id = mappings.mappedId(type.identifier());
Preconditions.checkArgument(id != -1, "Entity type %s has no id", type.identifier());
Preconditions.checkArgument(id < typesToFill.length, "Types array too small (missing enum entry?). Tried setting id %s into array of size %s", id, typesToFill.length);
idSetter.setId(type, id);
typesToFill[id] = type;
}
@@ -24,7 +24,9 @@ package com.viaversion.viaversion.util;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -60,6 +62,12 @@ public interface Rewritable {
return mappings == null ? itemId : (clientbound ? mappedIdentifier(mappings, itemId) : unmappedIdentifier(mappings, itemId));
}
static @Nullable Item rewriteItem(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound, final Item item) {
final ItemRewriter<?> rewriter = protocol.getItemRewriter();
return rewriter == null ? item
: (clientbound ? rewriter.handleItemToClient(connection, item) : rewriter.handleItemToServer(connection, item));
}
static Int2IntFunction itemRewriteFunction(final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return protocol.getMappingData().getItemMappings() == null ? Int2IntFunction.identity()
: (clientbound ? protocol.getMappingData()::getNewItemId : protocol.getMappingData()::getOldItemId);
+1 -2
View File
@@ -7,8 +7,7 @@ repositories {
}
dependencies {
// version must be manually kept in sync with the one in root project settings.gradle.kts
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.4.2")
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.6.1")
// A nice no-conflict comment for patching in downgrading
}
@@ -1,6 +1,5 @@
plugins {
`java-library`
`jvm-test-suite`
}
tasks {
Whitespace-only changes.
+2 -1
View File
@@ -1,6 +1,7 @@
plugins {
base
id("via.build-logic")
id("via.base-conventions") apply false
id("via.shadow-conventions") apply false
}
allprojects {
@@ -22,6 +22,7 @@ import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.bukkit.listeners.ViaBukkitListener;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.EfficiencyAttributeStorage;
import com.viaversion.viaversion.protocols.v1_20_5to1_21.storage.ProtocolStorables1_21;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@@ -55,7 +56,12 @@ public class PlayerChangeItemListener extends ViaBukkitListener {
}
protected EfficiencyAttributeStorage getEfficiencyStorage(final UserConnection connection) {
return connection != null ? connection.get(EfficiencyAttributeStorage.class) : null;
if (connection == null || !connection.isActive()) {
return null;
}
final ProtocolStorables1_21 storables = connection.storables(Protocol1_20_5To1_21.class);
return storables.efficiencyAttributes();
}
void sendAttributeUpdate(final Player player, @Nullable final ItemStack item, final Slot slot) {
+12 -6
View File
@@ -23,7 +23,8 @@ tasks.named<Jar>("sourcesJar") {
// Task to quickly test/debug code changes using https://github.com/ViaVersion/ViaProxy
// For further instructions see the ViaProxy repository README
val prepareViaProxyFiles by tasks.registering(Copy::class) {
val prepareViaProxyFiles = tasks.register<Copy>("prepareViaProxyFiles") {
description = "Prepares the ViaProxy run dir for the runViaProxy task"
dependsOn(project.tasks.shadowJar)
from(project.tasks.shadowJar.map { it.archiveFile.get().asFile })
@@ -33,27 +34,32 @@ val prepareViaProxyFiles by tasks.registering(Copy::class) {
rename { "${projectName}.jar" }
}
val cleanupViaProxyFiles by tasks.registering(Delete::class) {
val cleanupViaProxyFiles = tasks.register<Delete>("cleanupViaProxyFiles") {
description = "Deletes ViaProxy logs and the compiled project jar from its jars dir"
delete(
layout.projectDirectory.file("run/jars/${project.name}.jar"),
layout.projectDirectory.dir("run/logs")
)
}
val viaProxyConfiguration: Configuration by configurations.creating {
val viaProxyConfiguration: Configuration = configurations.create("viaProxyConfiguration") {
dependencies.add(rootProject.libs.viaProxy.get().copy().setTransitive(false))
}
tasks.register<JavaExec>("runViaProxy") {
description = "Runs ViaProxy locally"
dependsOn(prepareViaProxyFiles)
finalizedBy(cleanupViaProxyFiles)
mainClass.set("net.raphimc.viaproxy.ViaProxy")
classpath = viaProxyConfiguration
workingDir = layout.projectDirectory.dir("run").asFile
jvmArgs = listOf("-DskipUpdateCheck")
jvmArgs = listOf("-DskipUpdateCheck", "-Dviaproxy.gui.autoStart")
if (System.getProperty("viaproxy.gui.autoStart") != null) {
jvmArgs("-Dviaproxy.gui.autoStart")
if (System.getProperty("viaproxy.disableBackwardsPlatforms") != null) {
jvmArgs("-Dviaproxy.enableViaBackwards=false", "-Dviaproxy.enableViaRewind=false")
}
if (System.getProperty("viaproxy.disableExtraPlatforms") != null) {
jvmArgs("-Dviaproxy.enableViaBedrock=false", "-Dviaproxy.enableViaLegacy=false", "-Dviaproxy.enableViaAprilFools=false")
}
}
@@ -21,7 +21,6 @@ import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.Direction;
@@ -38,18 +37,19 @@ import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.rewriter.MappingDataListener;
import com.viaversion.viaversion.api.rewriter.Rewriter;
import com.viaversion.viaversion.connection.ProtocolStorablesBase;
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
import com.viaversion.viaversion.data.item.ItemHasherBase;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.protocol.ProtocolManagerImpl;
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
import com.viaversion.viaversion.rewriter.TagRewriter;
import com.viaversion.viaversion.rewriter.text.ComponentRewriterBase;
import com.viaversion.viaversion.util.ProtocolLogger;
import com.viaversion.viaversion.util.ProtocolUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Predicate;
import java.util.logging.Level;
@@ -75,6 +75,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
protected final PacketMappings clientboundMappings;
protected final PacketMappings serverboundMappings;
private final Map<Class<?>, Object> storedObjects = new HashMap<>();
private final int index = ProtocolManagerImpl.PROTOCOL_INDEX.getAndIncrement();
private boolean initialized;
private ProtocolLogger logger;
private ProtocolVersion serverVersion;
@@ -249,20 +250,15 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
protected void addEntityTracker(UserConnection connection) {
final EntityType playerEntityType = getEntityRewriter().typeFromId("player");
Preconditions.checkNotNull(playerEntityType, "Player entity type not found");
connection.addEntityTracker(this.getClass(), new EntityTrackerBase(connection, playerEntityType));
connection.storables(this).setEntityTracker(new EntityTrackerBase(connection, playerEntityType));
}
protected void addEntityTracker(UserConnection connection, EntityTracker tracker) {
connection.addEntityTracker(this.getClass(), tracker);
connection.storables(this).setEntityTracker(tracker);
}
protected void addItemHasher(UserConnection connection) {
connection.addItemHasher(this.getClass(), new ItemHasherBase(this, connection));
}
@Deprecated(forRemoval = true)
protected void addItemHasher(UserConnection connection, ItemHasher hasher) {
connection.addItemHasher(this.getClass(), hasher);
connection.storables(this).setItemHasher(new ItemHasherBase(this, connection));
}
protected PacketTypesProvider<CU, CM, SM, SU> createPacketTypesProvider() {
@@ -282,12 +278,12 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
return PacketMappings.arrayMappings();
}
/**
* Returns the server protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the server protocol version
*/
@Override
public ProtocolStorablesBase createStorables() {
return new ProtocolStorablesBase();
}
@Override
public @Nullable ProtocolVersion getServerVersion() {
return serverVersion;
}
@@ -302,12 +298,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
this.serverVersion = serverVersion;
}
/**
* Returns the client protocol version for this protocol,
* or null if not set (e.g. for base protocols).
*
* @return the client protocol version for this protocol
*/
@Override
public @Nullable ProtocolVersion getClientVersion() {
return clientVersion;
}
@@ -322,6 +313,11 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
this.clientVersion = clientVersion;
}
@Override
public int index() {
return index;
}
// ---------------------------------------------------------------------------------
@Override
@@ -30,7 +30,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
public class HashOps extends OpsBase implements Hasher {
/**
* Re-usable (but not thread-safe) ops for writing hashes.
*/
public final class HashOps extends OpsBase implements Hasher {
private static final byte TAG_MAP_START = 2;
private static final byte TAG_MAP_END = 3;
@@ -158,11 +161,6 @@ public class HashOps extends OpsBase implements Hasher {
mapHasher.applyHashToParent();
}
@Override
public <V> void write(final Type<V> type, final V value) {
type.write(this, value);
}
@Override
public int hash() {
return this.hashBuilder.hash();
@@ -0,0 +1,233 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.codec.nbt;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.DoubleTag;
import com.viaversion.nbt.tag.FloatTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.LongArrayTag;
import com.viaversion.nbt.tag.LongTag;
import com.viaversion.nbt.tag.ShortTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.codec.CodecContext;
import com.viaversion.viaversion.api.minecraft.codec.ThrowingOps;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.codec.OpsBase;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* Re-usable (but not thread-safe) ops for writing NBT.
*/
public final class NbtOps extends OpsBase {
private Tag result;
public NbtOps(final CodecContext context) {
super(context);
}
/**
* Serializes the given value into its NBT representation.
*
* @param context codec context
* @param type type of the value
* @param value value to serialize
* @param <V> value type
* @return the serialized tag
*/
public static <V> Tag serialize(final CodecContext context, final Type<V> type, final V value) {
final NbtOps ops = new NbtOps(context);
type.write(ops, value);
return ops.complete();
}
/**
* Returns the written tag, clearing it from this instance.
*
* @return the written tag
*/
public Tag complete() {
final Tag tag = this.result;
Preconditions.checkNotNull(tag, "No value written");
this.result = null;
return tag;
}
@Override
public void writeByte(final byte b) {
this.result = new ByteTag(b);
}
@Override
public void writeBytes(final byte[] array) {
this.result = new ByteArrayTag(array);
}
@Override
public void writeBoolean(final boolean b) {
this.result = new ByteTag(b);
}
@Override
public void writeShort(final short s) {
this.result = new ShortTag(s);
}
@Override
public void writeString(final CharSequence sequence) {
this.result = new StringTag(sequence.toString());
}
@Override
public void writeInt(final int i) {
this.result = new IntTag(i);
}
@Override
public void writeLong(final long l) {
this.result = new LongTag(l);
}
@Override
public void writeFloat(final float f) {
this.result = new FloatTag(f);
}
@Override
public void writeDouble(final double d) {
this.result = new DoubleTag(d);
}
@Override
public void writeInts(final int[] array) {
this.result = new IntArrayTag(array);
}
@Override
public void writeLongs(final long[] array) {
this.result = new LongArrayTag(array);
}
@Override
public void writeList(final Consumer<ListSerializer> consumer) {
final ListNbtSerializer serializer = new ListNbtSerializer();
consumer.accept(serializer);
// Only set after the consumer ran, nested writes use the same result field
this.result = ListTag.of(serializer.entries);
}
@Override
public void writeMap(final Consumer<MapSerializer> consumer) {
final MapNbtSerializer serializer = new MapNbtSerializer();
consumer.accept(serializer);
this.result = serializer.tag;
}
private <V> Tag serialize(final Type<V> type, final V value) {
type.write(this, value);
return complete();
}
private Tag serializeList(final Consumer<ListSerializer> consumer) {
writeList(consumer);
return complete();
}
private Tag serializeMap(final Consumer<MapSerializer> consumer) {
writeMap(consumer);
return complete();
}
private final class MapNbtSerializer implements MapSerializer {
private final CompoundTag tag = new CompoundTag();
@Override
public <K, V> MapSerializer write(final Type<K> keyType, final K key, final Type<V> valueType, final V value) {
tag.put(serializeKey(keyType, key), serialize(valueType, value));
return this;
}
@Override
public MapSerializer writeList(final String key, final Consumer<ListSerializer> consumer) {
tag.put(key, serializeList(consumer));
return this;
}
@Override
public MapSerializer writeMap(final String key, final Consumer<MapSerializer> consumer) {
tag.put(key, serializeMap(consumer));
return this;
}
@Override
public <T> MapSerializer writeInlinedMap(final Type<T> valueType, final T value) {
// Only allow writeMap calls here, writing its entries into this map
valueType.write(new ThrowingOps() {
@Override
public CodecContext context() {
return NbtOps.this.context();
}
@Override
public void writeMap(final Consumer<MapSerializer> consumer) {
consumer.accept(MapNbtSerializer.this);
}
}, value);
return this;
}
private <K> String serializeKey(final Type<K> keyType, final K key) {
final Tag keyTag = NbtOps.this.serialize(keyType, key);
Preconditions.checkArgument(keyTag instanceof StringTag, "Map keys have to be strings, got %s from %s", keyTag, keyType.getTypeName());
return ((StringTag) keyTag).getValue();
}
}
private final class ListNbtSerializer implements ListSerializer {
private final List<Tag> entries = new ArrayList<>();
@Override
public <V> ListSerializer write(final Type<V> valueType, final V value) {
entries.add(serialize(valueType, value));
return this;
}
@Override
public ListSerializer writeList(final Consumer<ListSerializer> consumer) {
entries.add(serializeList(consumer));
return this;
}
@Override
public ListSerializer writeMap(final Consumer<MapSerializer> consumer) {
entries.add(serializeMap(consumer));
return this;
}
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.connection;
import com.viaversion.viaversion.api.connection.ProtocolStorables;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
public class ProtocolStorablesBase implements ProtocolStorables {
private EntityTracker tracker;
private ClientWorld clientWorld;
private ItemHasher itemHasher;
@Override
public EntityTracker entityTracker() {
return tracker;
}
@Override
public void setEntityTracker(final EntityTracker tracker) {
this.tracker = tracker;
}
@Override
public ClientWorld clientWorld() {
return clientWorld;
}
@Override
public void setClientWorld(final ClientWorld clientWorld) {
this.clientWorld = clientWorld;
}
@Override
public ItemHasher itemHasher() {
return itemHasher;
}
@Override
public void setItemHasher(final ItemHasher itemHasher) {
this.itemHasher = itemHasher;
}
}
@@ -19,6 +19,7 @@ package com.viaversion.viaversion.connection;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.ProtocolInfo;
import com.viaversion.viaversion.api.connection.ProtocolStorables;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
@@ -44,8 +45,10 @@ import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.CodecException;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.SplittableRandom;
import java.util.concurrent.ConcurrentHashMap;
@@ -58,12 +61,10 @@ public class UserConnectionImpl implements UserConnection {
private static final AtomicLong IDS = new AtomicLong();
private final long id = IDS.incrementAndGet();
private final SplittableRandom random = new SplittableRandom();
private final Map<Class<?>, StorableObject> storedObjects = new ConcurrentHashMap<>();
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 Map<Class<?>, StorableObject> storedObjects = new ConcurrentHashMap<>(8);
private final ProtocolStorables[] protocolStorables = new ProtocolStorables[Via.getManager().getProtocolManager().registeredProtocolCount()];
private final PacketTracker packetTracker = new PacketTracker(this);
private final LongSet passthroughTokens = new LongOpenHashSet();
private final LongSet passthroughTokens = new LongOpenHashSet(4);
private final ProtocolInfo protocolInfo = new ProtocolInfoImpl();
private final Channel channel;
private final boolean clientSide;
@@ -71,7 +72,7 @@ public class UserConnectionImpl implements UserConnection {
private boolean pendingDisconnect;
/**
* Creates an UserConnection. When it's a client-side connection, some method behaviors are modified.
* Creates a UserConnection. When it's a client-side connection, some method behaviors are modified.
*
* @param channel netty channel.
* @param clientSide true if it's a client-side connection
@@ -117,37 +118,90 @@ public class UserConnectionImpl implements UserConnection {
@Override
public Collection<EntityTracker> getEntityTrackers() {
return entityTrackers.values();
final List<EntityTracker> trackers = new ArrayList<>();
for (final ProtocolStorables storable : protocolStorables) {
if (storable != null && storable.entityTracker() != null) {
trackers.add(storable.entityTracker());
}
}
return trackers;
}
@Override
public @Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass) {
return (T) entityTrackers.get(protocolClass);
final ProtocolStorables storables = storablesByClassIfPresent(protocolClass);
return storables != null ? (T) storables.entityTracker() : null;
}
@Override
public void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker) {
entityTrackers.putIfAbsent(protocolClass, tracker);
storables(protocolClass).setEntityTracker(tracker);
}
@Override
public void addItemHasher(final Class<? extends Protocol> protocolClass, final ItemHasher itemHasher) {
itemHashers.putIfAbsent(protocolClass, itemHasher);
storables(protocolClass).setItemHasher(itemHasher);
}
@Override
public @Nullable <T extends ItemHasher> T getItemHasher(Class<? extends Protocol> protocolClass) {
return (T) itemHashers.get(protocolClass);
final ProtocolStorables storables = storablesByClassIfPresent(protocolClass);
return storables != null ? (T) storables.itemHasher() : null;
}
@Override
public @Nullable <T extends ClientWorld> T getClientWorld(final Class<? extends Protocol> protocolClass) {
return (T) clientWorlds.get(protocolClass);
final ProtocolStorables storables = storablesByClassIfPresent(protocolClass);
return storables != null ? (T) storables.clientWorld() : null;
}
@Override
public void addClientWorld(final Class<? extends Protocol> protocolClass, final ClientWorld clientWorld) {
clientWorlds.putIfAbsent(protocolClass, clientWorld);
storables(protocolClass).setClientWorld(clientWorld);
}
private @Nullable ProtocolStorables storablesByClassIfPresent(final Class<? extends Protocol> protocolClass) {
final int index = protocolIndex(protocolClass);
return index >= 0 && index < protocolStorables.length ? protocolStorables[index] : null;
}
private static int protocolIndex(final Class<? extends Protocol> protocolClass) {
final Protocol<?, ?, ?, ?> protocol = Via.getManager().getProtocolManager().getProtocol(protocolClass);
return protocol != null ? protocol.index() : -1;
}
@Override
public @Nullable <T extends EntityTracker> T getEntityTracker(final Protocol<?, ?, ?, ?> protocol) {
final ProtocolStorables storables = storablesIfPresent(protocol);
//noinspection unchecked
return storables != null ? (T) storables.entityTracker() : null;
}
@Override
public @Nullable <T extends ItemHasher> T getItemHasher(final Protocol<?, ?, ?, ?> protocol) {
final ProtocolStorables storables = storablesIfPresent(protocol);
//noinspection unchecked
return storables != null ? (T) storables.itemHasher() : null;
}
@Override
public <T extends ProtocolStorables> T storables(final Protocol<?, ?, ?, ?> protocol) {
T storables = storablesIfPresent(protocol);
if (storables == null) {
//noinspection unchecked
storables = (T) protocol.createStorables();
protocolStorables[protocol.index()] = storables;
}
return storables;
}
public <T extends ProtocolStorables> T storablesIfPresent(final Protocol<?, ?, ?, ?> protocol) {
final int index = protocol.index();
if (index == -1) {
throw new IllegalArgumentException("Provided protocol does not have a valid index: " + index);
}
//noinspection unchecked
return (T) protocolStorables[index];
}
@Override
@@ -156,9 +210,7 @@ public class UserConnectionImpl implements UserConnection {
object.onRemove();
}
storedObjects.clear();
entityTrackers.clear();
itemHashers.clear();
clientWorlds.clear();
Arrays.fill(protocolStorables, null);
}
@Override
@@ -26,11 +26,11 @@ import com.viaversion.viaversion.util.ByteBufUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.ByteToMessageCodec;
import io.netty.handler.codec.MessageToMessageCodec;
import java.util.List;
public class ViaCodecHandler extends ByteToMessageCodec<ByteBuf> implements ViaChannelHandler {
public class ViaCodecHandler extends MessageToMessageCodec<ByteBuf, ByteBuf> implements ViaChannelHandler {
public static final String NAME = "via-codec";
@@ -41,14 +41,19 @@ public class ViaCodecHandler extends ByteToMessageCodec<ByteBuf> implements ViaC
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) {
protected void encode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
if (!this.connection.checkOutgoingPacket()) {
throw CancelEncoderException.generate(null);
}
out.writeBytes(in);
if (this.connection.shouldTransformPacket()) {
this.connection.transformOutgoing(out, CancelEncoderException::generate);
final ByteBuf transformedBuf = ByteBufUtil.copy(ctx.alloc(), in);
try {
if (this.connection.shouldTransformPacket()) {
this.connection.transformOutgoing(transformedBuf, CancelEncoderException::generate);
}
out.add(transformedBuf.retain());
} finally {
transformedBuf.release();
}
}
@@ -91,6 +91,7 @@ import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.Protocol1_9_1To1_9_3;
import com.viaversion.viaversion.protocols.v1_9_3to1_10.Protocol1_9_3To1_10;
import com.viaversion.viaversion.protocols.v1_9to1_9_1.Protocol1_9To1_9_1;
import com.viaversion.viaversion.protocols.v26_1to26_2.Protocol26_1To26_2;
import com.viaversion.viaversion.protocols.v26_2to26_3.Protocol26_2To26_3;
import com.viaversion.viaversion.util.MathUtil;
import com.viaversion.viaversion.util.Pair;
import io.netty.buffer.ByteBuf;
@@ -121,7 +122,8 @@ import java.util.logging.Level;
import org.checkerframework.checker.nullness.qual.Nullable;
public class ProtocolManagerImpl implements ProtocolManager {
private static final Protocol BASE_PROTOCOL = new InitialBaseProtocol();
public static final AtomicInteger PROTOCOL_INDEX = new AtomicInteger();
private static final InitialBaseProtocol BASE_PROTOCOL = new InitialBaseProtocol();
// Input Version -> Output Version & Protocol (Allows fast lookup)
private final Object2ObjectMap<ProtocolVersion, Object2ObjectMap<ProtocolVersion, Protocol>> registryMap = new Object2ObjectOpenHashMap<>(32);
@@ -221,6 +223,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
registerProtocol(new Protocol1_21_11To26_1(), ProtocolVersion.v26_1, ProtocolVersion.v1_21_11);
registerProtocol(new Protocol26_1To26_2(), ProtocolVersion.v26_2, ProtocolVersion.v26_1);
registerProtocol(new Protocol26_2To26_3(), ProtocolVersion.v26_3, ProtocolVersion.v26_2);
}
@Override
@@ -230,7 +233,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
@Override
public void registerProtocol(Protocol protocol, List<ProtocolVersion> supportedClientVersion, ProtocolVersion serverVersion) {
// Set the server version on AbstractProtocol instances before initialization
// Set the server version and index on AbstractProtocol instances before initialization
if (protocol instanceof AbstractProtocol<?, ?, ?, ?> abstractProtocol) {
abstractProtocol.setServerVersion(serverVersion);
abstractProtocol.setClientVersion(supportedClientVersion.stream().max(ProtocolVersion::compareTo).orElseThrow());
@@ -586,6 +589,11 @@ public class ProtocolManagerImpl implements ProtocolManager {
return mappingsLoaded;
}
@Override
public int registeredProtocolCount() {
return PROTOCOL_INDEX.get();
}
public void shutdownLoaderExecutor() {
Preconditions.checkArgument(!mappingsLoaded);
@@ -33,7 +33,8 @@ public final class DefaultRegistrations {
.to(ProtocolVersion.v1_20_5, EntityRegistrations::registerEntityPackets1_19)
.to(ProtocolVersion.v1_21_4, EntityRegistrations::registerEntityPackets1_20_5)
.to(ProtocolVersion.v1_21_9, EntityRegistrations::registerEntityPackets1_21_4)
.since(EntityRegistrations::registerEntityPackets1_21_9)
.to(ProtocolVersion.v26_3, EntityRegistrations::registerEntityPackets1_21_9)
.since(EntityRegistrations::registerEntityPackets26_3)
)
.ranges(ItemRegistrations::item, ProtocolVersion.v1_13, b -> b
@@ -50,7 +51,8 @@ public final class DefaultRegistrations {
)
.ranges(ItemRegistrations::structuredItem, ProtocolVersion.v1_21_5, b -> b
.to(ProtocolVersion.v1_21_6, ItemRegistrations::registerItemPackets1_21_5)
.since(ItemRegistrations::registerItemPackets1_21_6)
.to(ProtocolVersion.v26_3, ItemRegistrations::registerItemPackets1_21_6)
.since(ItemRegistrations::registerItemPackets26_3)
)
.ranges(BlockRegistrations::block, ProtocolVersion.v1_13, steps -> steps
@@ -71,7 +73,8 @@ public final class DefaultRegistrations {
.to(ProtocolVersion.v1_21_2, ParticleRegistrations::registerParticlePackets1_20_5)
.to(ProtocolVersion.v1_21_4, ParticleRegistrations::registerParticlePackets1_21_2)
.to(ProtocolVersion.v1_21_9, ParticleRegistrations::registerParticlePackets1_21_4)
.since(ParticleRegistrations::registerParticlePackets1_21_9)
.to(ProtocolVersion.v26_3, ParticleRegistrations::registerParticlePackets1_21_9)
.since(ParticleRegistrations::registerParticlePackets26_3)
)
.ranges(TextComponentRegistrations::text, ProtocolVersion.v1_12_2, b -> b
@@ -87,7 +90,8 @@ public final class DefaultRegistrations {
)
.ranges(TextComponentRegistrations::nbtText, ProtocolVersion.v1_21_5, b -> b
.to(ProtocolVersion.v26_2, TextComponentRegistrations::registerComponents1_21_5)
.since(TextComponentRegistrations::registerComponents26_2)
.to(ProtocolVersion.v26_3, TextComponentRegistrations::registerComponents26_2)
.since(TextComponentRegistrations::registerComponents26_3)
)
.ranges(ProtocolVersion.v1_17_1, sbeps -> sbeps
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPac
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
import com.viaversion.viaversion.protocols.v26_2to26_3.packet.ClientboundPackets26_3;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -84,6 +85,16 @@ final class EntityRegistrations {
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_ABILITIES, er::registerPlayerAbilities);
}
static <CU extends ClientboundPacketType> void registerEntityPackets26_3(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
ctx.clientbound(ClientboundPackets26_3.SET_ENTITY_DATA, er::registerSetEntityData);
ctx.clientbound(ClientboundPackets26_3.REMOVE_ENTITIES, er::registerRemoveEntities);
ctx.clientbound(ClientboundPackets26_3.LOGIN, er::registerLogin26_3);
ctx.clientbound(ClientboundPackets26_3.RESPAWN, er::registerRespawn26_3);
ctx.clientbound(ClientboundPackets26_3.GAME_EVENT, er::registerGameEvent);
ctx.clientbound(ClientboundPackets26_3.PLAYER_ABILITIES, er::registerPlayerAbilities);
ctx.clientbound(ClientboundPackets26_3.ADD_ENTITY, er::registerTrackerWithData1_21_9);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> EntityRewriter<CU, ?> entity(final RegistrationContext<CU, SU> ctx) {
return (EntityRewriter<CU, ?>) ctx.protocol().getEntityRewriter();
@@ -175,6 +175,22 @@ final class ItemRegistrations {
ctx.clientbound(ClientboundConfigurationPackets1_21_6.SHOW_DIALOG, ir::registerShowDialogDirect, PacketBound.ADDED_AT_MIN);
}
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets26_3(final RegistrationContext<CU, SU> ctx, final StructuredItemRewriter<CU, SU, ?> ir) {
ctx.clientbound(ClientboundPackets1_21_5.CONTAINER_SET_SLOT, ir::registerSetSlot1_21_2);
ctx.clientbound(ClientboundPackets1_21_5.CONTAINER_SET_CONTENT, ir::registerSetContent1_21_2);
ctx.clientbound(ClientboundPackets1_21_5.COOLDOWN, ir::registerCooldown1_21_2);
ctx.serverbound(ServerboundPackets1_21_5.CONTAINER_CLICK, ir::registerContainerClick1_21_5);
ctx.serverbound(ServerboundPackets1_21_5.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot1_21_5);
ctx.clientbound(ClientboundPackets1_21_5.SET_EQUIPMENT, ir::registerSetEquipment);
ctx.clientbound(ClientboundPackets1_21_5.OPEN_SCREEN, ir::registerOpenScreen);
ctx.clientbound(ClientboundPackets1_21_5.MERCHANT_OFFERS, ir::registerMerchantOffers1_20_5);
ctx.clientbound(ClientboundPackets1_21_5.SET_PLAYER_INVENTORY, ir::registerSetPlayerInventory);
ctx.clientbound(ClientboundPackets1_21_5.SET_CURSOR_ITEM, ir::registerSetCursorItem);
ctx.clientbound(ClientboundPackets1_21_6.SHOW_DIALOG, ir::registerShowDialog);
ctx.clientbound(ClientboundConfigurationPackets1_21_6.SHOW_DIALOG, ir::registerShowDialogDirect);
ctx.clientbound(ClientboundPackets1_21_5.UPDATE_ADVANCEMENTS, ir::registerAdvancements26_3);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ItemRewriter<CU, SU, ?> item(final RegistrationContext<CU, SU> ctx) {
return (ItemRewriter<CU, SU, ?>) ctx.protocol().getItemRewriter();
}
@@ -68,6 +68,11 @@ final class ParticleRegistrations {
ctx.clientbound(ClientboundPackets1_21_9.EXPLODE, pr::registerExplode1_21_9);
}
static <CU extends ClientboundPacketType> void registerParticlePackets26_3(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
ctx.clientbound(ClientboundPackets1_21_9.LEVEL_PARTICLES, pr::registerLevelParticles26_3);
ctx.clientbound(ClientboundPackets1_21_9.EXPLODE, pr::registerExplode1_21_9);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ParticleRewriter<CU> particle(final RegistrationContext<CU, SU> ctx) {
return (ParticleRewriter<CU>) ctx.protocol().getParticleRewriter();
}
@@ -191,6 +191,14 @@ final class TextComponentRegistrations {
ctx.clientbound(ClientboundPackets1_21_5.PLAYER_CHAT, cr::registerPlayerChat1_21_5);
}
static <CU extends ClientboundPacketType> void registerComponents26_3(final RegistrationContext<CU, ?> ctx, final NBTComponentRewriter<CU> cr) {
common1_20_5(ctx, cr);
ctx.clientbound(ClientboundPackets1_21_5.SET_PLAYER_TEAM, cr::registerSetPlayerTeam26_2);
ctx.clientbound(ClientboundPackets1_21_5.DISGUISED_CHAT, cr::registerDisguisedChat);
ctx.clientbound(ClientboundPackets1_21_5.PLAYER_INFO_UPDATE, cr::registerPlayerInfoUpdate1_21_4);
ctx.clientbound(ClientboundPackets1_21_5.PLAYER_CHAT, cr::registerPlayerChat26_3);
}
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ComponentRewriterBase<CU> text(final RegistrationContext<CU, SU> ctx) {
return (ComponentRewriterBase<CU>) ctx.protocol().getComponentRewriter();
}
@@ -38,8 +38,8 @@ final class BlockItemPacketRewriter99_1 extends StructuredItemRewriter<Clientbou
}
@Override
protected void backupInconvertibleData(final UserConnection connection, final Item item, final StructuredDataContainer dataContainer, final CompoundTag backupTag) {
super.backupInconvertibleData(connection, item, dataContainer, backupTag);
protected void backupInconvertibleData(final UserConnection connection, final Item item, final StructuredDataContainer container, final CompoundTag backupTag) {
super.backupInconvertibleData(connection, item, container, backupTag);
// back up any data if needed here, called before the method below
}
@@ -28,13 +28,16 @@ import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesP
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.connection.ProtocolStorablesBase;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
import com.viaversion.viaversion.protocols.v1_21_11to26_1.storage.ProtocolStorables26_1;
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.ServerboundPackets1_21_6;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
import com.viaversion.viaversion.protocols.v26_2to26_3.rewriter.RecipeDisplayRewriter26_3;
import com.viaversion.viaversion.rewriter.BlockRewriter;
import com.viaversion.viaversion.rewriter.ParticleRewriter;
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
@@ -60,7 +63,7 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
private final ParticleRewriter<ClientboundPacket26_1> particleRewriter = new ParticleRewriter<>(this);
private final TagRewriter<ClientboundPacket26_1> tagRewriter = new TagRewriter<>(this);
private final NBTComponentRewriter<ClientboundPacket26_1> componentRewriter = new ComponentRewriter99_1(this);
private final RecipeDisplayRewriter<ClientboundPacket26_1> recipeewriter = new RecipeDisplayRewriter1_21_5<>(this);
private final RecipeDisplayRewriter<ClientboundPacket26_1> recipeRewriter = new RecipeDisplayRewriter26_3<>(this);
private final RegistryDataRewriter registryDataRewriter = new RegistryDataRewriter(this);
public Protocol98_1To99_1() {
@@ -96,7 +99,7 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
// EntityTypes1_21_11.initialize(this);
// Uncomment if versioned types changed
// ParticleType.Fillers.fill1_21_9(this);
// ParticleType.Fillers.fill26_2(this);
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
}
@@ -108,6 +111,12 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
addItemHasher(connection);
}
// If data beyond the tracker and hasher is required
//@Override
//public ProtocolStorablesBase createStorables() {
// return new ProtocolStorables99_1();
//}
// Overriding these methods is important as they are relied on various rewriter classes
// and have mapping load methods called in AbstractProtocol via the getters
@Override
@@ -137,7 +146,7 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
@Override
public RecipeDisplayRewriter<ClientboundPacket26_1> getRecipeRewriter() {
return recipeewriter;
return recipeRewriter;
}
@Override
@@ -105,7 +105,7 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
});
registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_11.class);
ClientWorld clientWorld = wrapper.user().storables(this).clientWorld();
Chunk chunk = wrapper.passthrough(ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment()));
@@ -219,8 +219,8 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
@Override
public void init(UserConnection userConnection) {
userConnection.addEntityTracker(this.getClass(), new EntityTracker1_11(userConnection));
userConnection.addClientWorld(this.getClass(), new ClientWorld());
addEntityTracker(userConnection, new EntityTracker1_11(userConnection));
userConnection.storables(this).setClientWorld(new ClientWorld());
}
@Override
@@ -56,7 +56,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
map(Types.INT); // 2 - Dimension
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_11.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
int dimensionId = wrapper.get(Types.INT, 1);
clientWorld.setEnvironment(dimensionId);
});
@@ -68,7 +68,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
public void register() {
map(Types.INT);
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_11.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
int dimensionId = wrapper.get(Types.INT, 0);
if (clientWorld.setEnvironment(dimensionId)) {
tracker(wrapper.user()).clearEntities();
@@ -98,11 +98,11 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
tryFixFishingHookVelocity(wrapper);
} else if (type == EntityTypes1_10.ObjectType.ITEM.getId()) {
// Older clients used stone as fallback as long as the entity data was not set
final int entityId = wrapper.get(Types.VAR_INT, 0);
wrapper.send(Protocol1_10To1_11.class);
wrapper.cancel();
final int entityId = wrapper.get(Types.VAR_INT, 0);
final List<EntityData> entityDataList = new ArrayList<>();
entityDataList.add(new EntityData(6, EntityDataTypes1_9.ITEM, new DataItem(1, (byte) 1, null)));
@@ -142,7 +142,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
wrapper.set(Types.VAR_INT, 1, entType.getId());
// Register Type ID
wrapper.user().getEntityTracker(Protocol1_10To1_11.class).addEntity(entityId, entType);
wrapper.user().getEntityTracker(protocol).addEntity(entityId, entType);
handleEntityData(entityId, wrapper.get(Types.ENTITY_DATA_LIST1_9, 0), wrapper.user());
}
});
@@ -177,7 +177,7 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
handler(wrapper -> {
int entityID = wrapper.get(Types.VAR_INT, 0);
if (Via.getConfig().isHologramPatch()) {
EntityTracker1_11 tracker = wrapper.user().getEntityTracker(Protocol1_10To1_11.class);
EntityTracker1_11 tracker = wrapper.user().getEntityTracker(protocol);
if (tracker.isHologram(entityID)) {
Double newValue = wrapper.get(Types.DOUBLE, 1);
newValue -= (Via.getConfig().getHologramYOffset());
@@ -76,7 +76,7 @@ public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9
});
registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11_1To1_12.class);
ClientWorld clientWorld = wrapper.user().storables(this).clientWorld();
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
Chunk chunk = wrapper.passthrough(type);
@@ -173,8 +173,8 @@ public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9
@Override
public void init(UserConnection userConnection) {
userConnection.addEntityTracker(this.getClass(), new EntityTrackerBase(userConnection, EntityTypes1_12.EntityType.PLAYER));
userConnection.addClientWorld(this.getClass(), new ClientWorld());
addEntityTracker(userConnection, new EntityTrackerBase(userConnection, EntityTypes1_12.EntityType.PLAYER));
userConnection.storables(this).setClientWorld(new ClientWorld());
}
@Override
@@ -21,8 +21,11 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.util.ComponentUtil;
import com.viaversion.viaversion.util.SerializerVersion;
import com.viaversion.viaversion.util.StringUtil;
import java.util.logging.Level;
public final class ChatItemRewriter {
@@ -41,7 +44,15 @@ public final class ChatItemRewriter {
final JsonElement value = hoverEvent.get("value");
if (type.equals("show_item")) {
final CompoundTag compound = ComponentUtil.deserializeLegacyShowItem(value, SerializerVersion.V1_8);
final CompoundTag compound;
try {
compound = ComponentUtil.deserializeLegacyShowItem(value, SerializerVersion.V1_8);
} catch (final Exception e) {
if (Via.getConfig().logTextComponentConversionErrors()) {
Via.getPlatform().getLogger().log(Level.WARNING, "Error reading NBT in 1.8 show_item: " + StringUtil.forLogging(value), e);
}
return;
}
hoverEvent.addProperty("value", SerializerVersion.V1_12.toSNBT(compound));
}
} else if (obj.has("extra")) {
@@ -45,7 +45,7 @@ public class EntityPacketRewriter1_12 extends EntityRewriter<ClientboundPackets1
map(Types.UNSIGNED_BYTE);
map(Types.INT);
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11_1To1_12.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
int dimensionId = wrapper.get(Types.INT, 1);
clientWorld.setEnvironment(dimensionId);
@@ -63,7 +63,7 @@ public class EntityPacketRewriter1_12 extends EntityRewriter<ClientboundPackets1
public void register() {
map(Types.INT);
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11_1To1_12.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
int dimensionId = wrapper.get(Types.INT, 0);
if (clientWorld.setEnvironment(dimensionId)) {
tracker(wrapper.user()).clearEntities();
@@ -18,6 +18,7 @@
package com.viaversion.viaversion.protocols.v1_11to1_11_1;
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.protocols.v1_11to1_11_1.rewriter.ItemPacketRewriter1_11_1;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
@@ -33,6 +34,26 @@ public class Protocol1_11To1_11_1 extends AbstractProtocol<ClientboundPackets1_9
@Override
protected void registerPackets() {
itemRewriter.register();
registerClientbound(ClientboundPackets1_9_3.AWARD_STATS, wrapper -> {
int size = wrapper.passthrough(Types.VAR_INT);
int removed = 0;
for (int i = 0; i < size; i++) {
String name = wrapper.read(Types.STRING);
int value = wrapper.read(Types.VAR_INT);
if (name.equals("stat.treasureFished") || name.equals("stat.junkFished")) { // removed in 1.11.1
removed++;
continue;
}
wrapper.write(Types.STRING, name); // name
wrapper.write(Types.VAR_INT, value); // value
}
wrapper.set(Types.VAR_INT, 0, size - removed); // size
});
}
@Override
@@ -61,6 +61,7 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.rewriter.ItemPacketRewr
import com.viaversion.viaversion.protocols.v1_12_2to1_13.rewriter.WorldPacketRewriter1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.BlockConnectionStorage;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.BlockStorage;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.ProtocolStorables1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.TabCompleteTracker;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ServerboundPackets1_12_1;
@@ -248,9 +249,10 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
registerClientbound(ClientboundPackets1_12_1.COMMAND_SUGGESTIONS, wrapper -> {
wrapper.write(Types.VAR_INT, wrapper.user().get(TabCompleteTracker.class).getTransactionId());
final ProtocolStorables1_13 storables = wrapper.user().storables(this);
wrapper.write(Types.VAR_INT, storables.tabCompleteTracker().getTransactionId());
String input = wrapper.user().get(TabCompleteTracker.class).getInput();
String input = storables.tabCompleteTracker().getInput();
// Start & End
int index;
int length;
@@ -549,13 +551,15 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
}
int tid = wrapper.read(Types.VAR_INT);
// Save transaction id
wrapper.user().get(TabCompleteTracker.class).setTransactionId(tid);
final ProtocolStorables1_13 storables = wrapper.user().storables(Protocol1_12_2To1_13.this);
storables.tabCompleteTracker().setTransactionId(tid);
});
// Prepend /
map(Types.STRING, new ValueTransformer<>(Types.STRING) {
@Override
public String transform(PacketWrapper wrapper, String inputValue) {
wrapper.user().get(TabCompleteTracker.class).setInput(inputValue);
final ProtocolStorables1_13 storables = wrapper.user().storables(Protocol1_12_2To1_13.this);
storables.tabCompleteTracker().setInput(inputValue);
return "/" + inputValue;
}
});
@@ -565,7 +569,8 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
final BlockPosition playerLookTarget = Via.getManager().getProviders().get(PlayerLookTargetProvider.class).getPlayerLookTarget(wrapper.user());
wrapper.write(Types.OPTIONAL_POSITION1_8, playerLookTarget);
if (!wrapper.isCancelled() && Via.getConfig().get1_13TabCompleteDelay() > 0) {
TabCompleteTracker tracker = wrapper.user().get(TabCompleteTracker.class);
final ProtocolStorables1_13 storables = wrapper.user().storables(Protocol1_12_2To1_13.this);
final TabCompleteTracker tracker = storables.tabCompleteTracker();
wrapper.cancel();
tracker.setTimeToSend(System.currentTimeMillis() + Via.getConfig().get1_13TabCompleteDelay() * 50L);
tracker.setLastTabComplete(wrapper.get(Types.STRING, 0));
@@ -844,21 +849,28 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
@Override
public void init(UserConnection userConnection) {
userConnection.addEntityTracker(this.getClass(), new EntityTrackerBase(userConnection, EntityTypes1_13.EntityType.PLAYER));
userConnection.addClientWorld(this.getClass(), new ClientWorld());
userConnection.put(new TabCompleteTracker());
userConnection.put(new BlockStorage());
addEntityTracker(userConnection, new EntityTrackerBase(userConnection, EntityTypes1_13.EntityType.PLAYER));
final ProtocolStorables1_13 storables = userConnection.storables(this);
storables.setClientWorld(new ClientWorld());
userConnection.put(storables.tabCompleteTracker());
userConnection.put(storables.blockStorage());
if (Via.getConfig().isServersideBlockConnections()) {
if (Via.getManager().getProviders().get(BlockConnectionProvider.class) instanceof PacketBlockConnectionProvider) {
userConnection.put(new BlockConnectionStorage());
final BlockConnectionStorage blockConnectionStorage = new BlockConnectionStorage();
storables.setBlockConnectionStorage(blockConnectionStorage);
userConnection.put(blockConnectionStorage);
}
}
}
@Override
public ProtocolStorables1_13 createStorables() {
return new ProtocolStorables1_13();
}
@Override
public void register(ViaProviders providers) {
providers.register(BlockEntityProvider.class, new BlockEntityProvider());
providers.register(BlockEntityProvider.class, new BlockEntityProvider(this));
providers.register(PaintingProvider.class, new PaintingProvider());
providers.register(PlayerLookTargetProvider.class, new PlayerLookTargetProvider());
}
@@ -40,13 +40,13 @@ import java.util.Map;
public class BlockEntityProvider implements Provider {
private final Map<String, BlockEntityHandler> handlers = new HashMap<>();
public BlockEntityProvider() {
public BlockEntityProvider(final Protocol1_12_2To1_13 protocol) {
handlers.put("minecraft:flower_pot", new FlowerPotHandler());
handlers.put("minecraft:bed", new BedHandler());
handlers.put("minecraft:banner", new BannerHandler());
handlers.put("minecraft:skull", new SkullHandler());
handlers.put("minecraft:mob_spawner", new SpawnerHandler());
handlers.put("minecraft:command_block", new CommandBlockHandler());
handlers.put("minecraft:command_block", new CommandBlockHandler(protocol));
final BlockEntityHandler customNameHandler = (user, tag) -> {
final StringTag name = tag.getStringTag("CustomName");
@@ -29,7 +29,11 @@ import com.viaversion.viaversion.util.ComponentUtil;
public class CommandBlockHandler implements BlockEntityProvider.BlockEntityHandler {
private final Protocol1_12_2To1_13 protocol = Via.getManager().getProtocolManager().getProtocol(Protocol1_12_2To1_13.class);
private final Protocol1_12_2To1_13 protocol;
public CommandBlockHandler(final Protocol1_12_2To1_13 protocol) {
this.protocol = protocol;
}
@Override
public int transform(UserConnection user, CompoundTag tag) {
@@ -31,6 +31,7 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.Connec
import com.viaversion.viaversion.protocols.v1_12_2to1_13.data.EntityIdMappings1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.data.ParticleIdMappings1_13;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.BlockStorage;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.ProtocolStorables1_13;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
import com.viaversion.viaversion.rewriter.EntityRewriter;
import com.viaversion.viaversion.util.ComponentUtil;
@@ -65,7 +66,7 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
if (entType == null) return;
// Register Type ID
wrapper.user().getEntityTracker(Protocol1_12_2To1_13.class).addEntity(entityId, entType);
wrapper.user().getEntityTracker(protocol).addEntity(entityId, entType);
if (entType.is(EntityTypes1_13.EntityType.FALLING_BLOCK)) {
int oldId = wrapper.get(Types.INT, 0);
@@ -133,7 +134,7 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
map(Types.INT); // 2 - Dimension
handler(wrapper -> {
ClientWorld clientChunks = wrapper.user().getClientWorld(Protocol1_12_2To1_13.class);
ClientWorld clientChunks = wrapper.user().storables(protocol).clientWorld();
int dimensionId = wrapper.get(Types.INT, 1);
clientChunks.setEnvironment(dimensionId);
});
@@ -147,14 +148,15 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
public void register() {
map(Types.INT); // 0 - Dimension ID
handler(wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_12_2To1_13.class);
ClientWorld clientWorld = wrapper.user().storables(protocol).clientWorld();
int dimensionId = wrapper.get(Types.INT, 0);
if (clientWorld.setEnvironment(dimensionId)) {
if (Via.getConfig().isServersideBlockConnections()) {
ConnectionData.clearBlockStorage(wrapper.user());
}
tracker(wrapper.user()).clearEntities();
wrapper.user().get(BlockStorage.class).clear();
final ProtocolStorables1_13 storables = wrapper.user().storables(protocol);
storables.blockStorage().clear();
}
});
handler(Protocol1_12_2To1_13.SEND_DECLARE_COMMANDS_AND_TAGS);
@@ -44,6 +44,7 @@ import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ServerboundPacke
import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.BlockEntityProvider;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.provider.PaintingProvider;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.BlockStorage;
import com.viaversion.viaversion.protocols.v1_12_2to1_13.storage.ProtocolStorables1_13;
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
import com.viaversion.viaversion.util.IdAndData;
import com.viaversion.viaversion.util.Key;
@@ -113,7 +114,8 @@ public class WorldPacketRewriter1_13 {
int newId = provider.transform(wrapper.user(), position, tag, true);
if (newId != -1) {
BlockStorage storage = wrapper.user().get(BlockStorage.class);
final ProtocolStorables1_13 storables = wrapper.user().storables(protocol);
final BlockStorage storage = storables.blockStorage();
BlockStorage.ReplacementData replacementData = storage.get(position);
if (replacementData != null) {
replacementData.setReplacement(newId);
@@ -307,7 +309,8 @@ public class WorldPacketRewriter1_13 {
int x = wrapper.passthrough(Types.INT);
int z = wrapper.passthrough(Types.INT);
wrapper.user().get(BlockStorage.class).removeChunk(x, z);
final ProtocolStorables1_13 storables = wrapper.user().storables(protocol);
storables.blockStorage().removeChunk(x, z);
if (Via.getConfig().isServersideBlockConnections()) {
ConnectionData.blockConnectionProvider.unloadChunk(wrapper.user(), x, z);
}
@@ -328,8 +331,9 @@ public class WorldPacketRewriter1_13 {
});
protocol.registerClientbound(ClientboundPackets1_12_1.LEVEL_CHUNK, wrapper -> {
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_12_2To1_13.class);
BlockStorage storage = wrapper.user().get(BlockStorage.class);
final ProtocolStorables1_13 storables = wrapper.user().storables(protocol);
ClientWorld clientWorld = storables.clientWorld();
BlockStorage storage = storables.blockStorage();
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
ChunkType1_13 type1_13 = ChunkType1_13.forEnvironment(clientWorld.getEnvironment());
@@ -0,0 +1,44 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 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.storage;
import com.viaversion.viaversion.connection.ProtocolStorablesBase;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class ProtocolStorables1_13 extends ProtocolStorablesBase {
private final TabCompleteTracker tabCompleteTracker = new TabCompleteTracker();
private final BlockStorage blockStorage = new BlockStorage();
private BlockConnectionStorage blockConnectionStorage;
public TabCompleteTracker tabCompleteTracker() {
return tabCompleteTracker;
}
public BlockStorage blockStorage() {
return blockStorage;
}
public @Nullable BlockConnectionStorage blockConnectionStorage() {
return blockConnectionStorage;
}
public void setBlockConnectionStorage(final BlockConnectionStorage blockConnectionStorage) {
this.blockConnectionStorage = blockConnectionStorage;
}
}
@@ -113,8 +113,8 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
@Override
public void init(UserConnection userConnection) {
userConnection.addEntityTracker(this.getClass(), new EntityTracker1_14(userConnection));
userConnection.addClientWorld(this.getClass(), new ClientWorld());
addEntityTracker(userConnection, new EntityTracker1_14(userConnection));
userConnection.storables(this).setClientWorld(new ClientWorld());
}
@Override
Loaded 100 of 267 files, more files were not shown because too many files have changed in this diff. Show more