Compare commits

...
80 Commits
Author SHA1 Message Date
Nassim Jahnke 160eaa35aa 5.3.0 Release 2025-03-28 17:06:08 +01:00
Nassim Jahnke 9fb02581a6 Also check for hanging sign block entities 2025-03-28 17:04:59 +01:00
FlorianMichael 7d01d5363b Add TagUtil#getNamespacedTagKey and simplify code in component rewriter 2025-03-28 14:37:00 +01:00
Nassim Jahnke 8a549d7f11 And for disguised chat params 2025-03-28 14:12:41 +01:00
Nassim Jahnke 50e2db93b4 Also update name and target name 2025-03-28 14:12:41 +01:00
Nassim Jahnke 2d80c9526a Also process unsigned signed player chat 2025-03-28 14:12:41 +01:00
Nassim Jahnke 80d72121cf Check for horse saddles in entity data too 2025-03-28 14:12:41 +01:00
Nassim Jahnke ba11b3c214 Remove show_in_tooltip 2025-03-28 14:12:41 +01:00
Nassim Jahnke 2ee4c86dcb Remote snapshot version 2025-03-28 14:12:41 +01:00
Nassim Jahnke 97b8cbbc6f 1.21.5-rc2 2025-03-28 14:12:40 +01:00
riku6460 1a1ae41a7b Fix blockEntityHandler not being called when mappedId == id 2025-03-28 14:12:40 +01:00
Nassim Jahnke 2b7a86bc55 Play shield break and block sounds from entity events 2025-03-28 14:12:40 +01:00
Nassim Jahnke 175c320389 Simplify server container desync check with Paper API if present
Fixes desyncs on item drags due to missing item data for 1.21.5+ clients
2025-03-28 14:12:40 +01:00
RK_01 b22430a923 Moved hashed item conversion code into method (#16)
Allows for easy injection in platforms like ViaProxy or ViaFabricPlus
2025-03-28 14:12:40 +01:00
Nassim Jahnke c9f9e88ebe 1.21.5-rc1 2025-03-28 14:12:40 +01:00
Nassim Jahnke 7f0b3fc241 1.21.5-pre3 2025-03-28 14:12:39 +01:00
RK_01 e13b99e73a Use new blocks_attacks component for 1.8 sword blocking (#15) 2025-03-28 14:12:39 +01:00
Nassim Jahnke 304d9f04ec Send saddle equipment for pigs and striders 2025-03-28 14:12:39 +01:00
Nassim Jahnke 92b59fd904 Update dependencies 2025-03-28 14:12:39 +01:00
Nassim Jahnke 7e42ce2a5c 1.21.5-pre2 2025-03-28 14:12:39 +01:00
Nassim Jahnke d3475dc751 Fix pig saddle index 2025-03-28 14:12:39 +01:00
Nassim Jahnke cd6e5a3d7a 1.21.5-pre1 2025-03-28 14:12:38 +01:00
Nassim Jahnke 67e50ed6f4 Add missing provides_banner_patterns item data, fix entity variants 2025-03-28 14:12:38 +01:00
Nassim Jahnke 097ad1c721 Add helper methods for removing data components 2025-03-28 14:12:38 +01:00
FlorianMichael 6a4f5732e2 Handle show_in_tooltip values in chat item components 2025-03-28 14:12:38 +01:00
Nassim Jahnke 000769e7c5 Adventure mode predicate changes
🫠
2025-03-28 14:12:38 +01:00
Nassim Jahnke c725242713 Fix block entity removal OOB 2025-03-28 14:12:37 +01:00
Nassim Jahnke fd9d7d674b 25w10a 2025-03-28 14:12:37 +01:00
Nassim Jahnke 5c87388353 Update mappings 2025-03-28 14:12:37 +01:00
Nassim Jahnke 3b65720d04 Update ViaNBT 2025-03-28 14:12:37 +01:00
Nassim Jahnke 44af621c12 25w09b 2025-03-28 14:12:37 +01:00
Nassim Jahnke 4e33615d9e Update sign text 2025-03-28 14:12:37 +01:00
Nassim Jahnke a5b34b9fac 25w09a 2025-03-28 14:12:37 +01:00
Nassim Jahnke 674b81a5ce 25w08a 2025-03-28 14:12:36 +01:00
Nassim Jahnke 36a3a7bd32 Fix read of single value storage 2025-03-28 14:12:36 +01:00
Nassim Jahnke d2b2f56438 25w07a 2025-03-28 14:12:36 +01:00
Nassim Jahnke 5cb147f8c5 25w06a 2025-03-28 14:12:36 +01:00
Nassim Jahnke c1c6d7378d Fix optional holder type 2025-03-28 14:12:36 +01:00
Nassim Jahnke 3cd9d8c20b 25w05a 2025-03-28 14:12:35 +01:00
Nassim Jahnke 8faa00af14 Finish up things 2025-03-28 14:12:35 +01:00
Nassim Jahnke 2aa02cfc20 Mostly finished 25w04a 2025-03-28 14:12:35 +01:00
Nassim Jahnke 1071e68e6e Update show_text value key 2025-03-28 14:12:35 +01:00
Nassim Jahnke bcf4efacc5 Remove block entities if mapped to nothing 2025-03-28 14:12:35 +01:00
Nassim Jahnke 4ab3148dd9 25w03a 2025-03-28 14:12:34 +01:00
Nassim Jahnke b0269b53b7 Offset pig variant entity data type 2025-03-28 14:12:34 +01:00
Nassim Jahnke 5df2ffe6a8 Handle hover and click event changes
Changes to the component rewriter will be done in the public branch
2025-03-28 14:12:34 +01:00
Nassim Jahnke 0e8e58dc5c WIP 25w02a 2025-03-28 14:12:34 +01:00
FlorianMichael d1e27617a9 Update warning when no working pipe is found (#4416) 2025-03-26 21:24:19 +01:00
FlorianMichael 5ab4f49148 Add Copyable interface and unify copy() methods (#4413) 2025-03-25 16:37:00 +01:00
FlorianMichael 494da63b66 Rewrite ConnectionManager to track client/server connections (#4410) 2025-03-12 16:51:34 +01:00
Nassim Jahnke a0b0ed4b68 Make <1.21.2 container id types consistent with Vanilla again
... that's to say, to make them inconsistent thanks to special ids:
Byte:
- CONTAINER_SET_SLOT
- CONTAINER_CLICK
- PLACE_GHOST_RECIPE
- PLACE_RECIPE
- CONTAINER_BUTTON_CLICK
- CONTAINER_CLOSE (serverbound)
- CONTAINER_ACK (serverbound)
Unsigned byte (unchanged):
- OPEN_SCREEN
- CONTAINER_SET_CONTENT
- CONTAINER_SET_DATA
- HORSE_SCREEN_OPEN
- CONTAINER_CLOSE (clientbound)
- CONTAINER_ACK (clientbound)
Short (unchanged):
- SET_CREATIVE_MODE_SLOT

This doesn't change much in practice, but means it matches the Vanilla reading
2025-03-11 10:36:49 +01:00
FlorianMichael e9ec29a217 Javadoc fixes (#4391) 2025-03-08 15:21:24 +01:00
FlorianMichaelandNassim Jahnke fb5bc8254a Add connection details protocol implementation (#4371)
Adds an optional custom payload protocol which platforms can use to communicate the native version of users across backend servers, the current implementation supports Velocity by sending the player's native version to the backend servers. Platforms may call ConnectionDetails#sendConnectionDetails themselves to ensure the packet getting handled by the server.

Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2025-03-04 15:54:37 +01:00
FlorianMichael a7bc03f6a9 Treat changes in client bound base protocol handlers as separate protocols (#4400) 2025-02-27 22:31:35 +01:00
github-actions[bot]andgradle-update-robot d1bea0326c Update Gradle Wrapper from 8.12.1 to 8.13 (#4396)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-02-25 18:40:57 +01:00
Nassim Jahnke d3512c9e7f Check overrides too when removing item data 2025-02-25 13:42:52 +01:00
Nassim Jahnke 2f1f7538e5 Ignore invalid ingredients in registry data 2025-02-23 11:10:04 +01:00
FlorianMichael ac3362f950 Don't add damage types twice in 1.19.4->1.20 (#4389)
Closes https://github.com/ViaVersion/ViaFabricPlus/issues/652
2025-02-19 14:13:52 +01:00
FlorianMichael 74e510b056 Fix clientEntityId check in MovementTransmitterProvider (#4390) 2025-02-19 14:13:24 +01:00
FlorianMichael fdd263b806 Make functions optional which are not always required in ViaPlatform (#4370) 2025-02-16 13:56:32 +01:00
FlorianMichael a764cec4a9 Add DebugHandler#logPrePacketTransform/setLogPacketTransform (#4386) 2025-02-16 13:55:20 +01:00
FlorianMichael 764861e29b [ci skip] Migrate the user wiki to GitHub (#4382) 2025-02-10 15:37:14 +01:00
EnZaXD 3e946ff67e Add user feedback to /viaversion list & player if no players are found (#4369) 2025-01-31 22:36:39 +01:00
Nassim Jahnke dca45ceb0e Simplify read error 2025-01-30 17:13:12 +01:00
Florian 327ec23ae9 Add PacketTypeMap#ofUnsequenced helper function (#4368) 2025-01-30 13:51:10 +01:00
Florian 9cf7737502 Fix container hover event deserialization (#4365) 2025-01-29 15:37:38 +01:00
Florian 0c5fa1b00a Add ProtocolRunnable internal API (#4364) 2025-01-29 15:36:57 +01:00
EnZaXD 1ca075fe89 Only add minecraft:spit damage type if not sent by the server in 1.20.3->1.20.5 (#4361) 2025-01-27 22:03:12 +01:00
EnZaXD d7c50a0c06 Remove newly added registry entries when already sent be the server (#4352)
Closes https://github.com/ViaVersion/ViaFabricPlus/issues/683
2025-01-26 22:15:48 +01:00
github-actions[bot]andgradle-update-robot 0e98839cee Update Gradle Wrapper from 8.12 to 8.12.1 (#4359)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-01-26 20:01:35 +01:00
EnZaXD 512ceeb401 Rewrite sound event in consumable/equippable components (#4358) 2025-01-25 22:15:55 +01:00
lowercasebtwandEnZaXD 1bf04b4769 Use "intentionally_empty" sound event for 1.8 blocking (#4357)
* Use "intentionally_empty" sound event for 1.8 blocking

* Rather use the sound identifier

---------

Co-authored-by: EnZaXD <florian.michael07@gmail.com>
2025-01-24 22:31:35 +01:00
Nassim Jahnke e24981031b Fix optional explosions hover event deserialization
Fixes ViaVersion/ViaBackwards#952
2025-01-17 12:29:20 +01:00
Nassim Jahnke 261188569d Update custom model data in items in block entities 2025-01-16 13:15:22 +01:00
EnZaXD d2f35708ed Add tag->component handlers in 1.20.5->1.21 component rewriter (#4172)
Used for hover event handling in ViaBackwards
2025-01-15 11:51:44 +01:00
EnZaXD d282f37483 Fix tracking of falling blocks (#4344)
* Fix tracking of falling blocks

Since they use the data int, we have to try get() without taking it in as it will otherwise always fail.

* Prevent server from sending bad data

* Null check
2025-01-11 23:04:22 +01:00
Nassim Jahnke b244776cc9 Move up method to ComponentRewriter interface 2025-01-10 21:25:38 +01:00
Nassim Jahnke 3418e2c21a Prepare ComponentRewriter for 1.21.5 changes 2025-01-10 20:56:36 +01:00
EnZaXD d05bdd9eda Keep empty items in CONTAINER in 1.20.3->1.20.5 (#4338) 2025-01-10 17:43:12 +01:00
EnZaXD a92e75b8cc Properly track minecart object entity types in <= 1.12.2 (#4339) 2025-01-10 17:07:09 +01:00
217 changed files with 7361 additions and 1390 deletions

No files matched your search

+1 -1
View File
@@ -18,7 +18,7 @@ Supported Versions:
![Table (https://i.imgur.com/zrQTcf0.png)](https://i.imgur.com/zrQTcf0.png)
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
**User Docs:** https://docs.viaversion.com
Snapshot support
--------
@@ -114,7 +114,8 @@ public interface ViaAPI<T> {
ProtocolVersion getPlayerProtocolVersion(UUID uuid);
/**
* Returns whether Via injected into this player connection.
* Returns whether Via injected into this player connection. Note that this method may not work on
* clientside implementations and is generally not recommended to be used. Use {@link ConnectionManager} instead.
*
* @param uuid uuid of the player
* @return whether Via has a cached a UserConnection for this player
@@ -122,7 +123,8 @@ public interface ViaAPI<T> {
boolean isInjected(UUID uuid);
/**
* Returns the Via injected UserConnection if present.
* Returns whether Via injected into this player connection. Note that this method may not work on
* clientside implementations and is generally not recommended to be used. Use {@link ConnectionManager} instead.
*
* @param uuid uuid of the player
* @return user connection if present
@@ -66,7 +66,7 @@ public interface ViaSubCommand {
*
* @param sender Command sender
* @param args Arguments
* @return commands executed succesfully if false, show usage
* @return commands executed successfully if false, show usage
*/
boolean execute(ViaCommandSender sender, String[] args);
@@ -30,7 +30,7 @@ public interface ViaVersionCommand {
* Register your own subcommand inside ViaVersion
*
* @param command Your own SubCommand instance to handle it.
* @throws IllegalArgumentException throws an exception when the subcommand already exists or if it's not valid, example: spacee
* @throws IllegalArgumentException throws an exception when the subcommand already exists or if it's not valid, example: space
*/
void registerSubCommand(ViaSubCommand command);
@@ -28,51 +28,81 @@ import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Handles injected UserConnections
* Handles injected UserConnections.
* Check {@link UserConnection#isServerSide()} and {@link UserConnection#isClientSide()} to determine the connection type.
*/
public interface ConnectionManager {
/**
* Returns if Via injected into this player connection.
* Returns if Via has injected. See above for the connection types.
*
* @param playerId player uuid
* @param uuid player uuid
* @return true if the player is handled by Via
*/
boolean isClientConnected(UUID playerId);
boolean hasServerConnection(UUID uuid);
/**
* Frontend connections will have the UUID stored. Override this if your platform isn't always frontend.
* UUIDs can't be duplicate between frontend connections.
*
* @return true if the user is a frontend connection
*/
default boolean isFrontEnd(UserConnection connection) {
return !connection.isClientSide();
@Deprecated
default boolean isClientConnected(UUID uuid) {
return hasServerConnection(uuid);
}
/**
* Returns the frontend UserConnection from the player connected to this proxy server
* Returns null when there isn't a server or connection was not found
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
* Returns if Via has injected. See above for the connection types.
*
* @return frontend UserConnection of the player connected to this proxy server
* @param uuid player uuid
* @return true if the player is handled by Via
*/
@Nullable UserConnection getConnectedClient(UUID clientIdentifier);
boolean hasClientConnection(UUID uuid);
/**
* Returns the UUID from the frontend connection to this proxy server
* Returns null when there isn't a server or this connection isn't frontend, or it doesn't have an id
* Returns the server UserConnection. See above for the connection types.
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
*
* @return UUID of the frontend connection to this proxy server
* @return server UserConnection of the player or null
*/
@Nullable UUID getConnectedClientId(UserConnection connection);
@Nullable
UserConnection getServerConnection(UUID uuid);
@Deprecated
@Nullable default UserConnection getConnectedClient(UUID uuid) {
return getServerConnection(uuid);
}
/**
* Returns the client UserConnection. See above for the connection types.
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
*
* @return client UserConnection of the player or null
*/
@Nullable
UserConnection getClientConnection(UUID uuid);
/**
* Returns a map containing the UUIDs and server UserConnections
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and frontend UserConnections
*/
Map<UUID, UserConnection> getServerConnections();
@Deprecated
default Map<UUID, UserConnection> getConnectedClients() {
return getServerConnections();
}
/**
* Returns a map containing the UUIDs and client UserConnections
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and client UserConnections
*/
Map<UUID, UserConnection> getClientConnections();
/**
* Returns all UserConnections which are registered
@@ -84,15 +114,6 @@ public interface ConnectionManager {
*/
Set<UserConnection> getConnections();
/**
* Returns a map containing the UUIDs and frontend UserConnections from players connected to this proxy server
* Returns empty list when there isn't a server
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and frontend UserConnections from players connected to this proxy server
*/
Map<UUID, UserConnection> getConnectedClients();
void onLoginSuccess(UserConnection connection);
void onDisconnect(UserConnection connection);
@@ -319,23 +319,35 @@ public interface UserConnection {
void setPendingDisconnect(boolean pendingDisconnect);
/**
* Returns whether this is a client-side connection.
* This is a mod integrated into the client itself, or for example a backend Velocity connection.
* Returns whether this is a backend connection.
* This is a mod integrated into the client, or for example a backend Velocity connection.
*
* @return whether this is a client-side connection
* @return whether this is a backend connection
*/
boolean isClientSide();
/**
* Returns whether this is a frontend connection.
* This is a plugin integrated into the server, or for example a frontend Velocity connection.
*
* @return whether this is a frontend connection
*/
default boolean isServerSide() {
return !isClientSide();
}
/**
* Returns whether {@link ViaVersionConfig#blockedProtocolVersions()} should be checked for this connection.
*
* @return whether blocked protocols should be applied
*/
boolean shouldApplyBlockProtocol();
default boolean shouldApplyBlockProtocol() {
return isServerSide();
}
/**
* Returns a newly generated uuid that will let a packet be passed through without
* transformig its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
* transforming its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
*
* @return generated passthrough token
*/
@@ -22,7 +22,6 @@
*/
package com.viaversion.viaversion.api.debug;
import com.google.common.annotations.Beta;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
@@ -50,7 +49,6 @@ public interface DebugHandler {
*
* @param packetTypeName packet type name
*/
@Beta
void addPacketTypeNameToLog(String packetTypeName);
/**
@@ -59,7 +57,6 @@ public interface DebugHandler {
*
* @param packetType packet type
*/
@Beta
void addPacketTypeToLog(PacketType packetType);
/**
@@ -67,22 +64,44 @@ public interface DebugHandler {
*
* @param packetTypeName packet type name
*/
@Beta
boolean removePacketTypeNameToLog(String packetTypeName);
/**
* Resets packet type filters.
*/
@Beta
void clearPacketTypesToLog();
/**
* Sets whether packets should be logged before and after being transformed.
*
* @param logPacketTransform whether packets should be logged
*/
default void setLogPacketTransform(boolean logPacketTransform) {
setLogPrePacketTransform(logPacketTransform);
setLogPostPacketTransform(logPacketTransform);
}
/**
* Returns whether packets should be logged before being transformed.
* Set to true by default.
*
* @return whether packets should be logged before being transformed
*/
boolean logPrePacketTransform();
/**
* Sets whether packets should be logged before being transformed.
*
* @param logPrePacketTransform whether packets should be logged before being transformed
*/
void setLogPrePacketTransform(boolean logPrePacketTransform);
/**
* Returns whether packets should be logged after being transformed.
* Set to false by default.
*
* @return whether packets should be logged after being transformed
*/
@Beta
boolean logPostPacketTransform();
/**
@@ -90,7 +109,6 @@ public interface DebugHandler {
*
* @param logPostPacketTransform whether packets should be logged after being transformed
*/
@Beta
void setLogPostPacketTransform(boolean logPostPacketTransform);
/**
@@ -103,7 +121,6 @@ public interface DebugHandler {
*/
boolean shouldLog(PacketWrapper wrapper, Direction direction);
@Beta
default void enableAndLogIds(final PacketType... packetTypes) {
setEnabled(true);
for (final PacketType packetType : packetTypes) {
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents an animal variant (e.g. for cows, pigs, chickens).
*
* @param modelType model type id
* @param texture texture path
* @param biomes biomes this variant can spawn in, if limited to specific biomes
*/
public record AnimalVariant(int modelType, String texture, @Nullable HolderSet biomes) {
public static HolderType<AnimalVariant> TYPE = new HolderType<>() {
@Override
public AnimalVariant readDirect(final ByteBuf buffer) {
final int modelType = Types.VAR_INT.readPrimitive(buffer);
final String texture = Types.STRING.read(buffer);
final HolderSet biomes = Types.OPTIONAL_HOLDER_SET.read(buffer);
return new AnimalVariant(modelType, texture, biomes);
}
@Override
public void writeDirect(final ByteBuf buffer, final AnimalVariant variant) {
Types.VAR_INT.writePrimitive(buffer, variant.modelType());
Types.STRING.write(buffer, variant.texture());
Types.OPTIONAL_HOLDER_SET.write(buffer, variant.biomes());
}
};
}
@@ -0,0 +1,82 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
public interface EitherHolder<T> {
/**
* Returns a direct or indirect value holder.
*
* @param value the value
* @param <T> the type of the value
* @return a new direct holder
*/
static <T> EitherHolder<T> of(final Holder<T> value) {
return new EitherHolderImpl<>(value, null);
}
/**
* Returns an indirect holder via the resource key.
*
* @param key the resource key
* @param <T> the type of the value
* @return a new holder with the given resource key
*/
static <T> EitherHolder<T> of(final String key) {
return new EitherHolderImpl<>(null, key);
}
/**
* Returns true if this holder is backed by a direct value.
*
* @return true if the holder is direct
* @see #hasKey()
*/
boolean hasHolder();
/**
* Returns true if this holder has a resource key.
*
* @return true if this holder has a resource key
* @see #hasHolder()
*/
boolean hasKey();
/**
* Returns the value of this holder.
*
* @return the value of this holder
* @throws IllegalArgumentException if this contains a resource key instead of a holder
* @see #hasHolder()
*/
Holder<T> holder();
/**
* Returns the resource key.
*
* @return the resource key
* @throws IllegalArgumentException if this contains a holder instead of a resource key
* @see #hasKey()
*/
String key();
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.util.EitherImpl;
final class EitherHolderImpl<T> extends EitherImpl<Holder<T>, String> implements EitherHolder<T> {
EitherHolderImpl(final Holder<T> left, final String value) {
super(left, value);
}
@Override
public boolean hasHolder() {
return isLeft();
}
@Override
public boolean hasKey() {
return isRight();
}
@Override
public Holder<T> holder() {
Preconditions.checkArgument(hasHolder(), "Either does not have a holder");
return left();
}
@Override
public String key() {
Preconditions.checkArgument(hasKey(), "Either does not have a key");
return right();
}
}
@@ -22,15 +22,15 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.IdHolder;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class Particle implements IdHolder {
public final class Particle implements IdHolder, Copyable {
private final List<ParticleData<?>> arguments = new ArrayList<>(4);
private int id;
@@ -73,6 +73,7 @@ public final class Particle implements IdHolder {
arguments.set(index, new ParticleData<>(type, value));
}
@Override
public Particle copy() {
final Particle particle = new Particle(id);
for (ParticleData<?> argument : arguments) {
@@ -89,7 +90,7 @@ public final class Particle implements IdHolder {
'}';
}
public static final class ParticleData<T> {
public static final class ParticleData<T> implements Copyable {
private final Type<T> type;
private T value;
@@ -118,12 +119,9 @@ public final class Particle implements IdHolder {
wrapper.write(type, value);
}
@Override
public ParticleData<T> copy() {
if (value instanceof Item item) {
return new ParticleData<>(type, (T) item.copy());
} else {
return new ParticleData<>(type, value);
}
return new ParticleData<>(type, copy(value));
}
@Override
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.Copyable;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@@ -31,12 +32,13 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* @param key key of the registry entry
* @param tag data of the registry entry, or null if the client should use its default
*/
public record RegistryEntry(String key, @Nullable Tag tag) {
public record RegistryEntry(String key, @Nullable Tag tag) implements Copyable {
public RegistryEntry withKey(final String key) {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
@Override
public RegistryEntry copy() {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
@@ -143,6 +143,16 @@ public class BaseChunk implements Chunk {
this.heightMap = heightMap;
}
@Override
public Heightmap[] heightmaps() {
throw new UnsupportedOperationException();
}
@Override
public void setHeightmaps(final Heightmap[] heightmaps) {
throw new UnsupportedOperationException();
}
@Override
public List<CompoundTag> getBlockEntities() {
return blockEntities;
@@ -79,7 +79,8 @@ public interface Chunk {
* @return chunk section bit mask, only non-null for 1.17+ chunks
* @see #getBitmask()
*/
@Nullable BitSet getChunkMask();
@Nullable
BitSet getChunkMask();
void setChunkMask(BitSet chunkSectionMask);
@@ -88,7 +89,8 @@ public interface Chunk {
*
* @return array of nullable chunk sections
*/
@Nullable ChunkSection[] getSections();
@Nullable
ChunkSection[] getSections();
void setSections(ChunkSection[] sections);
@@ -106,10 +108,15 @@ public interface Chunk {
*
* @return compoundtag containing heightmaps if present
*/
@Nullable CompoundTag getHeightMap();
@Nullable
CompoundTag getHeightMap();
void setHeightMap(@Nullable CompoundTag heightMap);
Heightmap[] heightmaps();
void setHeightmaps(Heightmap[] heightmaps);
/**
* Returns a list of block entities.
*
@@ -123,6 +123,16 @@ public class Chunk1_18 implements Chunk {
this.heightMap = heightMap;
}
@Override
public Heightmap[] heightmaps() {
throw new UnsupportedOperationException();
}
@Override
public void setHeightmaps(final Heightmap[] heightmaps) {
throw new UnsupportedOperationException();
}
@Override
public List<CompoundTag> getBlockEntities() {
throw new UnsupportedOperationException();
@@ -0,0 +1,145 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import java.util.BitSet;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public class Chunk1_21_5 implements Chunk {
protected final int x;
protected final int z;
protected ChunkSection[] sections;
protected Heightmap[] heightmaps;
protected final List<BlockEntity> blockEntities;
public Chunk1_21_5(int x, int z, ChunkSection[] sections, Heightmap[] heightmaps, List<BlockEntity> blockEntities) {
this.x = x;
this.z = z;
this.sections = sections;
this.heightmaps = heightmaps;
this.blockEntities = blockEntities;
}
@Override
public boolean isBiomeData() {
return false;
}
@Override
public int getX() {
return x;
}
@Override
public int getZ() {
return z;
}
@Override
public boolean isFullChunk() {
return true;
}
@Override
public boolean isIgnoreOldLightData() {
return false;
}
@Override
public void setIgnoreOldLightData(boolean ignoreOldLightData) {
throw new UnsupportedOperationException();
}
@Override
public int getBitmask() {
return -1;
}
@Override
public void setBitmask(int bitmask) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable BitSet getChunkMask() {
return null;
}
@Override
public void setChunkMask(BitSet chunkSectionMask) {
throw new UnsupportedOperationException();
}
@Override
public ChunkSection[] getSections() {
return sections;
}
@Override
public void setSections(ChunkSection[] sections) {
this.sections = sections;
}
@Override
public int @Nullable [] getBiomeData() {
return null;
}
@Override
public void setBiomeData(int @Nullable [] biomeData) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable CompoundTag getHeightMap() {
throw new UnsupportedOperationException();
}
@Override
public void setHeightMap(final CompoundTag heightMap) {
throw new UnsupportedOperationException();
}
@Override
public Heightmap[] heightmaps() {
return heightmaps;
}
@Override
public void setHeightmaps(final Heightmap[] heightmaps) {
this.heightmaps = heightmaps;
}
@Override
public List<CompoundTag> getBlockEntities() {
throw new UnsupportedOperationException();
}
@Override
public List<BlockEntity> blockEntities() {
return blockEntities;
}
}
@@ -0,0 +1,26 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.chunks;
public record Heightmap(int type, long[] data) {
}
@@ -53,6 +53,11 @@ final class EmptyStructuredData<T> implements StructuredData<T> {
return this.key;
}
@Override
public StructuredData<T> copy() {
return new EmptyStructuredData<>(this.key, this.id);
}
@Override
public T value() {
return null;
@@ -59,6 +59,11 @@ final class FilledStructuredData<T> implements StructuredData<T> {
return key;
}
@Override
public StructuredData<T> copy() {
return new FilledStructuredData<>(this.key, this.copy(this.value), this.id);
}
@Override
public T value() {
return value;
@@ -22,11 +22,12 @@
*/
package com.viaversion.viaversion.api.minecraft.data;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.IdHolder;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface StructuredData<T> extends IdHolder {
public interface StructuredData<T> extends IdHolder, Copyable {
/**
* Returns filled structured data, equivalent to an Optional with a value in vanilla.
@@ -52,7 +53,8 @@ public interface StructuredData<T> extends IdHolder {
return new EmptyStructuredData<>(key, id);
}
@Nullable T value();
@Nullable
T value();
void setValue(final T value);
@@ -60,6 +62,9 @@ public interface StructuredData<T> extends IdHolder {
StructuredDataKey<T> key();
@Override
StructuredData<T> copy();
/**
* Returns whether the structured data is present. Even if true, the value may be null.
*
@@ -26,9 +26,11 @@ import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Unit;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import java.util.Collection;
import java.util.Map;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -53,7 +55,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
* </ul>
* Other methods (e.g. {@link #getData(StructuredDataKey)} and {@link #has(StructuredDataKey)}) will handle both empty and non-empty data.
*/
public final class StructuredDataContainer {
public final class StructuredDataContainer implements Copyable {
private final Map<StructuredDataKey<?>, StructuredData<?>> data;
private FullMappings lookup;
@@ -71,7 +73,7 @@ public final class StructuredDataContainer {
}
public StructuredDataContainer() {
this(new Reference2ObjectOpenHashMap<>());
this(new Reference2ObjectOpenHashMap<>(0));
}
/**
@@ -188,6 +190,20 @@ public final class StructuredDataContainer {
this.data.remove(key);
}
/**
* Removes data by the given keys.
*
* @param keys data keys
* @see #replace(StructuredDataKey, Function)
* @see #replace(StructuredDataKey, StructuredDataKey, Function)
* @see #replaceKey(StructuredDataKey, StructuredDataKey)
*/
public void remove(final Collection<StructuredDataKey<?>> keys) {
for (final StructuredDataKey<?> key : keys) {
this.data.remove(key);
}
}
/**
* Returns whether there is data for the given key, either empty or non-empty.
*
@@ -245,8 +261,13 @@ public final class StructuredDataContainer {
}
}
@Override
public StructuredDataContainer copy() {
final StructuredDataContainer copy = new StructuredDataContainer(new Reference2ObjectOpenHashMap<>(data));
final Reference2ObjectOpenHashMap<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>();
for (final StructuredData<?> value : data.values()) {
map.put(value.key(), value.copy());
}
final StructuredDataContainer copy = new StructuredDataContainer(map);
copy.lookup = this.lookup;
return copy;
}
@@ -24,17 +24,22 @@ package com.viaversion.viaversion.api.minecraft.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.GameProfile;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
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.AdventureModePredicate.AdventureModePredicateType1_21_5;
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrim;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_20_5;
import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
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.CustomModelData1_21_4;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant;
@@ -53,18 +58,24 @@ import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
import com.viaversion.viaversion.api.minecraft.item.data.ProvidesTrimMaterial;
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
import com.viaversion.viaversion.api.minecraft.item.data.TooltipDisplay;
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.Weapon;
import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.EitherType;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
import com.viaversion.viaversion.api.type.types.version.Types1_21_4;
import com.viaversion.viaversion.api.type.types.version.Types1_21_5;
import com.viaversion.viaversion.util.Either;
import com.viaversion.viaversion.util.Unit;
public record StructuredDataKey<T>(String identifier, Type<T> type) {
@@ -73,21 +84,27 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> MAX_STACK_SIZE = new StructuredDataKey<>("max_stack_size", Types.VAR_INT);
public static final StructuredDataKey<Integer> MAX_DAMAGE = new StructuredDataKey<>("max_damage", Types.VAR_INT);
public static final StructuredDataKey<Integer> DAMAGE = new StructuredDataKey<>("damage", Types.VAR_INT);
public static final StructuredDataKey<Unbreakable> UNBREAKABLE = new StructuredDataKey<>("unbreakable", Unbreakable.TYPE);
public static final StructuredDataKey<Unbreakable> UNBREAKABLE1_20_5 = new StructuredDataKey<>("unbreakable", Unbreakable.TYPE);
public static final StructuredDataKey<Unit> UNBREAKABLE1_21_5 = new StructuredDataKey<>("unbreakable", Types.EMPTY);
public static final StructuredDataKey<Tag> CUSTOM_NAME = new StructuredDataKey<>("custom_name", Types.TAG);
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TAG);
public static final StructuredDataKey<String> ITEM_MODEL = new StructuredDataKey<>("item_model", Types.STRING);
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", new ArrayType<>(Types.TAG, 256));
public static final StructuredDataKey<Integer> RARITY = new StructuredDataKey<>("rarity", Types.VAR_INT);
public static final StructuredDataKey<Enchantments> ENCHANTMENTS = new StructuredDataKey<>("enchantments", Enchantments.TYPE);
public static final StructuredDataKey<AdventureModePredicate> CAN_PLACE_ON = new StructuredDataKey<>("can_place_on", AdventureModePredicate.TYPE);
public static final StructuredDataKey<AdventureModePredicate> CAN_BREAK = new StructuredDataKey<>("can_break", AdventureModePredicate.TYPE);
public static final StructuredDataKey<Enchantments> ENCHANTMENTS1_20_5 = new StructuredDataKey<>("enchantments", Enchantments.TYPE1_20_5);
public static final StructuredDataKey<Enchantments> ENCHANTMENTS1_21_5 = new StructuredDataKey<>("enchantments", Enchantments.TYPE1_21_5);
public static final StructuredDataKey<AdventureModePredicate> CAN_PLACE_ON1_20_5 = new StructuredDataKey<>("can_place_on", AdventureModePredicate.TYPE1_20_5);
public static final StructuredDataKey<AdventureModePredicate> CAN_PLACE_ON1_21_5 = new StructuredDataKey<>("can_place_on", new AdventureModePredicateType1_21_5(Types1_21_5.STRUCTURED_DATA_ARRAY));
public static final StructuredDataKey<AdventureModePredicate> CAN_BREAK1_20_5 = new StructuredDataKey<>("can_break", AdventureModePredicate.TYPE1_20_5);
public static final StructuredDataKey<AdventureModePredicate> CAN_BREAK1_21_5 = new StructuredDataKey<>("can_break", new AdventureModePredicateType1_21_5(Types1_21_5.STRUCTURED_DATA_ARRAY));
public static final StructuredDataKey<AttributeModifiers1_20_5> ATTRIBUTE_MODIFIERS1_20_5 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_20_5.TYPE);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE1_21);
public static final StructuredDataKey<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21_5 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE1_21_5);
public static final StructuredDataKey<Integer> CUSTOM_MODEL_DATA1_20_5 = new StructuredDataKey<>("custom_model_data", Types.VAR_INT);
public static final StructuredDataKey<CustomModelData1_21_4> CUSTOM_MODEL_DATA1_21_4 = new StructuredDataKey<>("custom_model_data", CustomModelData1_21_4.TYPE);
public static final StructuredDataKey<Unit> HIDE_ADDITIONAL_TOOLTIP = new StructuredDataKey<>("hide_additional_tooltip", Types.EMPTY);
public static final StructuredDataKey<Unit> HIDE_TOOLTIP = new StructuredDataKey<>("hide_tooltip", Types.EMPTY);
public static final StructuredDataKey<TooltipDisplay> TOOLTIP_DISPLAY = new StructuredDataKey<>("tooltip_display", TooltipDisplay.TYPE);
public static final StructuredDataKey<Integer> REPAIR_COST = new StructuredDataKey<>("repair_cost", Types.VAR_INT);
public static final StructuredDataKey<Unit> CREATIVE_SLOT_LOCK = new StructuredDataKey<>("creative_slot_lock", Types.EMPTY);
public static final StructuredDataKey<Boolean> ENCHANTMENT_GLINT_OVERRIDE = new StructuredDataKey<>("enchantment_glint_override", Types.BOOLEAN);
@@ -98,18 +115,25 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
public static final StructuredDataKey<Item> USE_REMAINDER1_21_2 = new StructuredDataKey<>("use_remainder", Types1_21_2.ITEM);
public static final StructuredDataKey<Item> USE_REMAINDER1_21_4 = new StructuredDataKey<>("use_remainder", Types1_21_4.ITEM);
public static final StructuredDataKey<Item> USE_REMAINDER1_21_5 = new StructuredDataKey<>("use_remainder", Types1_21_5.ITEM);
public static final StructuredDataKey<UseCooldown> USE_COOLDOWN = new StructuredDataKey<>("use_cooldown", UseCooldown.TYPE);
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
public static final StructuredDataKey<DamageResistant> DAMAGE_RESISTANT = new StructuredDataKey<>("damage_resistant", DamageResistant.TYPE);
public static final StructuredDataKey<ToolProperties> TOOL = new StructuredDataKey<>("tool", ToolProperties.TYPE);
public static final StructuredDataKey<ToolProperties> TOOL1_20_5 = new StructuredDataKey<>("tool", ToolProperties.TYPE1_20_5);
public static final StructuredDataKey<ToolProperties> TOOL1_21_5 = new StructuredDataKey<>("tool", ToolProperties.TYPE1_21_5);
public static final StructuredDataKey<Weapon> WEAPON = new StructuredDataKey<>("weapon", Weapon.TYPE);
public static final StructuredDataKey<Integer> ENCHANTABLE = new StructuredDataKey<>("enchantable", Types.VAR_INT);
public static final StructuredDataKey<Equippable> EQUIPPABLE = new StructuredDataKey<>("equippable", Equippable.TYPE);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_2 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_2);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_5 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_5);
public static final StructuredDataKey<HolderSet> REPAIRABLE = new StructuredDataKey<>("repairable", Types.HOLDER_SET);
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
public static final StructuredDataKey<String> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.STRING);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE);
public static final StructuredDataKey<DyedColor> DYED_COLOR = new StructuredDataKey<>("dyed_color", DyedColor.TYPE);
public static final StructuredDataKey<BlocksAttacks> BLOCKS_ATTACKS = new StructuredDataKey<>("blocks_attacks", BlocksAttacks.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<DyedColor> DYED_COLOR1_20_5 = new StructuredDataKey<>("dyed_color", DyedColor.TYPE1_20_5);
public static final StructuredDataKey<DyedColor> DYED_COLOR1_21_5 = new StructuredDataKey<>("dyed_color", DyedColor.TYPE1_21_5);
public static final StructuredDataKey<Integer> MAP_COLOR = new StructuredDataKey<>("map_color", Types.INT);
public static final StructuredDataKey<Integer> MAP_ID = new StructuredDataKey<>("map_id", Types.VAR_INT);
public static final StructuredDataKey<CompoundTag> MAP_DECORATIONS = new StructuredDataKey<>("map_decorations", Types.COMPOUND_TAG);
@@ -118,26 +142,34 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21 = new StructuredDataKey<>("charged_projectiles", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_2 = new StructuredDataKey<>("charged_projectiles", Types1_21_2.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_4 = new StructuredDataKey<>("charged_projectiles", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_5 = new StructuredDataKey<>("charged_projectiles", Types1_21_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_20_5 = new StructuredDataKey<>("bundle_contents", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21 = new StructuredDataKey<>("bundle_contents", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_2 = new StructuredDataKey<>("bundle_contents", Types1_21_2.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_4 = new StructuredDataKey<>("bundle_contents", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_5 = new StructuredDataKey<>("bundle_contents", Types1_21_5.ITEM_ARRAY);
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_20_5 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_20_5);
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_21_2 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_21_2);
public static final StructuredDataKey<Float> POTION_DURATION_SCALE = new StructuredDataKey<>("potion_duration_scale", Types.FLOAT);
public static final StructuredDataKey<SuspiciousStewEffect[]> SUSPICIOUS_STEW_EFFECTS = new StructuredDataKey<>("suspicious_stew_effects", SuspiciousStewEffect.ARRAY_TYPE);
public static final StructuredDataKey<FilterableString[]> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", FilterableString.ARRAY_TYPE);
public static final StructuredDataKey<WrittenBook> WRITTEN_BOOK_CONTENT = new StructuredDataKey<>("written_book_content", WrittenBook.TYPE);
public static final StructuredDataKey<ArmorTrim> 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<CompoundTag> DEBUG_STICK_STATE = new StructuredDataKey<>("debug_stick_state", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> ENTITY_DATA = new StructuredDataKey<>("entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> BUCKET_ENTITY_DATA = new StructuredDataKey<>("bucket_entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<CompoundTag> BLOCK_ENTITY_DATA = new StructuredDataKey<>("block_entity_data", Types.COMPOUND_TAG);
public static final StructuredDataKey<Holder<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<EitherHolder<Instrument1_21_2>> INSTRUMENT1_21_5 = new StructuredDataKey<>("instrument", Instrument1_21_2.EITHER_HOLDER_TYPE);
public static final StructuredDataKey<ProvidesTrimMaterial> PROVIDES_TRIM_MATERIAL = new StructuredDataKey<>("provides_trim_material", ProvidesTrimMaterial.TYPE);
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE);
public static final StructuredDataKey<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);
public static final StructuredDataKey<String> PROVIDES_BANNER_PATTERNS = new StructuredDataKey<>("provides_banner_patterns", Types.STRING);
public static final StructuredDataKey<Tag> RECIPES = new StructuredDataKey<>("recipes", Types.TAG);
public static final StructuredDataKey<LodestoneTracker> LODESTONE_TRACKER = new StructuredDataKey<>("lodestone_tracker", LodestoneTracker.TYPE);
public static final StructuredDataKey<FireworkExplosion> FIREWORK_EXPLOSION = new StructuredDataKey<>("firework_explosion", FireworkExplosion.TYPE);
@@ -151,10 +183,37 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Item[]> CONTAINER1_21 = new StructuredDataKey<>("container", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_21_2 = new StructuredDataKey<>("container", new ArrayType<>(Types1_21_2.ITEM, 256));
public static final StructuredDataKey<Item[]> CONTAINER1_21_4 = new StructuredDataKey<>("container", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_21_5 = new StructuredDataKey<>("container", Types1_21_5.ITEM_ARRAY);
public static final StructuredDataKey<BlockStateProperties> BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE);
public static final StructuredDataKey<Bee[]> BEES = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE);
public static final StructuredDataKey<Tag> LOCK = new StructuredDataKey<>("lock", Types.TAG);
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<Integer> VILLAGER_VARIANT = new StructuredDataKey<>("villager/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> WOLF_VARIANT = new StructuredDataKey<>("wolf/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> WOLF_SOUND_VARIANT = new StructuredDataKey<>("wolf/sound_variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> WOLF_COLLAR = new StructuredDataKey<>("wolf/collar", Types.VAR_INT);
public static final StructuredDataKey<Integer> FOX_VARIANT = new StructuredDataKey<>("fox/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> SALMON_SIZE = new StructuredDataKey<>("salmon/size", Types.VAR_INT);
public static final StructuredDataKey<Integer> PARROT_VARIANT = new StructuredDataKey<>("parrot/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> TROPICAL_FISH_PATTERN = new StructuredDataKey<>("tropical_fish/pattern", Types.VAR_INT);
public static final StructuredDataKey<Integer> TROPICAL_FISH_BASE_COLOR = new StructuredDataKey<>("tropical_fish/base_color", Types.VAR_INT);
public static final StructuredDataKey<Integer> TROPICAL_FISH_PATTERN_COLOR = new StructuredDataKey<>("tropical_fish/pattern_color", Types.VAR_INT);
public static final StructuredDataKey<Integer> MOOSHROOM_VARIANT = new StructuredDataKey<>("mooshroom/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> RABBIT_VARIANT = new StructuredDataKey<>("rabbit/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> PIG_VARIANT = new StructuredDataKey<>("pig/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> COW_VARIANT = new StructuredDataKey<>("cow/variant", Types.VAR_INT);
public static final StructuredDataKey<Either<Integer, String>> CHICKEN_VARIANT = new StructuredDataKey<>("chicken/variant", new EitherType<>(Types.VAR_INT, Types.STRING)); // ???
public static final StructuredDataKey<Integer> FROG_VARIANT = new StructuredDataKey<>("frog/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> HORSE_VARIANT = new StructuredDataKey<>("horse/variant", Types.VAR_INT);
public static final StructuredDataKey<Holder<PaintingVariant>> PAINTING_VARIANT = new StructuredDataKey<>("painting/variant", PaintingVariant.TYPE1_21_2);
public static final StructuredDataKey<Integer> LLAMA_VARIANT = new StructuredDataKey<>("llama/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> AXOLOTL_VARIANT = new StructuredDataKey<>("axolotl/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> CAT_VARIANT = new StructuredDataKey<>("cat/variant", Types.VAR_INT);
public static final StructuredDataKey<Integer> CAT_COLLAR = new StructuredDataKey<>("cat/collar", Types.VAR_INT);
public static final StructuredDataKey<Integer> SHEEP_COLOR = new StructuredDataKey<>("sheep/color", Types.VAR_INT);
public static final StructuredDataKey<Integer> SHULKER_COLOR = new StructuredDataKey<>("shulker/color", Types.VAR_INT);
@Override
public String toString() {
@@ -0,0 +1,52 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.predicate;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public record DataComponentMatchers(StructuredData<?>[] exactPredicates, DataComponentPredicate[] predicates) {
public static final class DataComponentMatchersType extends Type<DataComponentMatchers> {
private final Type<StructuredData<?>[]> dataArrayType;
public DataComponentMatchersType(final Type<StructuredData<?>[]> dataArrayType) {
super(DataComponentMatchers.class);
this.dataArrayType = dataArrayType;
}
@Override
public DataComponentMatchers read(final ByteBuf buffer) {
final StructuredData<?>[] exactPredicates = dataArrayType.read(buffer);
final DataComponentPredicate[] partialPredicates = DataComponentPredicate.ARRAY_TYPE.read(buffer);
return new DataComponentMatchers(exactPredicates, partialPredicates);
}
@Override
public void write(final ByteBuf buffer, final DataComponentMatchers value) {
dataArrayType.write(buffer, value.exactPredicates());
DataComponentPredicate.ARRAY_TYPE.write(buffer, value.predicates());
}
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.data.predicate;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
public record DataComponentPredicate(int id, Tag predicate) {
public static final Type<DataComponentPredicate> TYPE = new Type<>(DataComponentPredicate.class) {
@Override
public DataComponentPredicate read(final ByteBuf buffer) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final Tag predicate = Types.TAG.read(buffer);
return new DataComponentPredicate(id, predicate);
}
@Override
public void write(final ByteBuf buffer, final DataComponentPredicate value) {
Types.VAR_INT.writePrimitive(buffer, value.id());
Types.TAG.write(buffer, value.predicate());
}
};
public static final Type<DataComponentPredicate[]> ARRAY_TYPE = new ArrayType<>(TYPE, 64);
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_10 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -212,7 +201,13 @@ public class EntityTypes1_10 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -235,19 +230,25 @@ public class EntityTypes1_10 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -256,20 +257,28 @@ public class EntityTypes1_10 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_11 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -237,7 +226,13 @@ public class EntityTypes1_11 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -262,19 +257,25 @@ public class EntityTypes1_11 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -283,20 +284,28 @@ public class EntityTypes1_11 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_12 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -243,7 +232,13 @@ public class EntityTypes1_12 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -268,19 +263,25 @@ public class EntityTypes1_12 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -289,20 +290,28 @@ public class EntityTypes1_12 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_13 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -254,7 +243,13 @@ public class EntityTypes1_13 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -280,19 +275,25 @@ public class EntityTypes1_13 {
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL),
TRIDENT(94, EntityType.TRIDENT);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -301,20 +302,28 @@ public class EntityTypes1_13 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -0,0 +1,317 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entities;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.util.EntityTypeUtil;
import com.viaversion.viaversion.util.Key;
import java.util.Locale;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum EntityTypes1_21_5 implements EntityType {
ENTITY(null, null),
AREA_EFFECT_CLOUD(ENTITY),
END_CRYSTAL(ENTITY),
EVOKER_FANGS(ENTITY),
EXPERIENCE_ORB(ENTITY),
EYE_OF_ENDER(ENTITY),
FALLING_BLOCK(ENTITY),
ITEM(ENTITY),
TNT(ENTITY),
OMINOUS_ITEM_SPAWNER(ENTITY),
MARKER(ENTITY),
LIGHTNING_BOLT(ENTITY),
INTERACTION(ENTITY),
DISPLAY(ENTITY, null),
BLOCK_DISPLAY(DISPLAY),
ITEM_DISPLAY(DISPLAY),
TEXT_DISPLAY(DISPLAY),
// Hanging entities
HANGING_ENTITY(ENTITY, null),
LEASH_KNOT(HANGING_ENTITY),
PAINTING(HANGING_ENTITY),
ITEM_FRAME(HANGING_ENTITY),
GLOW_ITEM_FRAME(ITEM_FRAME),
// Projectiles
PROJECTILE(ENTITY, null),
ITEM_PROJECTILE(PROJECTILE, null),
SNOWBALL(ITEM_PROJECTILE),
ENDER_PEARL(ITEM_PROJECTILE),
EGG(ITEM_PROJECTILE),
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),
// Living entities as a larger subclass
LIVING_ENTITY(ENTITY, null),
ARMOR_STAND(LIVING_ENTITY),
PLAYER(LIVING_ENTITY),
// Mobs as a larger subclass
MOB(LIVING_ENTITY, null),
ENDER_DRAGON(MOB),
SLIME(MOB),
MAGMA_CUBE(SLIME),
// Ambient mobs
AMBIENT_CREATURE(MOB, null),
BAT(AMBIENT_CREATURE),
// Flying mobs
FLYING_MOB(MOB, null),
GHAST(FLYING_MOB),
PHANTOM(FLYING_MOB),
// Pathfinder mobs and its subclasses
PATHFINDER_MOB(MOB, null),
ALLAY(PATHFINDER_MOB),
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
SNOW_GOLEM(ABSTRACT_GOLEM),
IRON_GOLEM(ABSTRACT_GOLEM),
SHULKER(ABSTRACT_GOLEM),
// Ageable mobs and (tamable) animals
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
VILLAGER(ABSTRACT_VILLAGER),
WANDERING_TRADER(ABSTRACT_VILLAGER),
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
AXOLOTL(ABSTRACT_ANIMAL),
CHICKEN(ABSTRACT_ANIMAL),
PANDA(ABSTRACT_ANIMAL),
PIG(ABSTRACT_ANIMAL),
POLAR_BEAR(ABSTRACT_ANIMAL),
RABBIT(ABSTRACT_ANIMAL),
SHEEP(ABSTRACT_ANIMAL),
BEE(ABSTRACT_ANIMAL),
TURTLE(ABSTRACT_ANIMAL),
FOX(ABSTRACT_ANIMAL),
FROG(ABSTRACT_ANIMAL),
GOAT(ABSTRACT_ANIMAL),
HOGLIN(ABSTRACT_ANIMAL),
STRIDER(ABSTRACT_ANIMAL),
SNIFFER(ABSTRACT_ANIMAL),
ARMADILLO(ABSTRACT_ANIMAL),
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
COW(ABSTRACT_COW),
MOOSHROOM(ABSTRACT_COW),
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
CAT(TAMABLE_ANIMAL),
OCELOT(TAMABLE_ANIMAL),
WOLF(TAMABLE_ANIMAL),
PARROT(TAMABLE_ANIMAL),
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
HORSE(ABSTRACT_HORSE),
SKELETON_HORSE(ABSTRACT_HORSE),
ZOMBIE_HORSE(ABSTRACT_HORSE),
CAMEL(ABSTRACT_HORSE),
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
DONKEY(ABSTRACT_CHESTED_HORSE),
MULE(ABSTRACT_CHESTED_HORSE),
LLAMA(ABSTRACT_CHESTED_HORSE),
TRADER_LLAMA(LLAMA),
// Monsters
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
BLAZE(ABSTRACT_MONSTER),
CREEPER(ABSTRACT_MONSTER),
ENDERMITE(ABSTRACT_MONSTER),
ENDERMAN(ABSTRACT_MONSTER),
GIANT(ABSTRACT_MONSTER),
SILVERFISH(ABSTRACT_MONSTER),
VEX(ABSTRACT_MONSTER),
WITHER(ABSTRACT_MONSTER),
BREEZE(ABSTRACT_MONSTER),
ZOGLIN(ABSTRACT_MONSTER),
WARDEN(ABSTRACT_MONSTER),
CREAKING(ABSTRACT_MONSTER),
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
SKELETON(ABSTRACT_SKELETON),
STRAY(ABSTRACT_SKELETON),
WITHER_SKELETON(ABSTRACT_SKELETON),
BOGGED(ABSTRACT_SKELETON),
ZOMBIE(ABSTRACT_MONSTER),
DROWNED(ZOMBIE),
HUSK(ZOMBIE),
ZOMBIFIED_PIGLIN(ZOMBIE),
ZOMBIE_VILLAGER(ZOMBIE),
GUARDIAN(ABSTRACT_MONSTER),
ELDER_GUARDIAN(GUARDIAN),
SPIDER(ABSTRACT_MONSTER),
CAVE_SPIDER(SPIDER),
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
PIGLIN(ABSTRACT_PIGLIN),
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
// Water mobs
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
DOLPHIN(AGEABLE_WATER_CREATURE),
SQUID(AGEABLE_WATER_CREATURE),
GLOW_SQUID(SQUID),
WATER_ANIMAL(PATHFINDER_MOB, null),
ABSTRACT_FISH(WATER_ANIMAL, null),
PUFFERFISH(ABSTRACT_FISH),
TADPOLE(ABSTRACT_FISH),
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
COD(ABSTRACT_SCHOOLING_FISH),
SALMON(ABSTRACT_SCHOOLING_FISH),
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
// Raiders
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
WITCH(ABSTRACT_RAIDER),
RAVAGER(ABSTRACT_RAIDER),
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
VINDICATOR(ABSTRACT_ILLAGER),
PILLAGER(ABSTRACT_ILLAGER),
EVOKER(SPELLCASTER_ILLAGER),
ILLUSIONER(SPELLCASTER_ILLAGER);
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
private final EntityType parent;
private final String identifier;
private int id = -1;
EntityTypes1_21_5(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes1_21_5(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);
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_8 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -203,7 +192,13 @@ public class EntityTypes1_8 {
public enum ObjectType implements com.viaversion.viaversion.api.minecraft.entities.ObjectType {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -223,19 +218,25 @@ public class EntityTypes1_8 {
ARMOR_STAND(78, EntityType.ARMOR_STAND),
FISHIHNG_HOOK(90, EntityType.FISHING_HOOK);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -244,20 +245,28 @@ public class EntityTypes1_8 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -27,17 +27,6 @@ import java.util.Map;
public class EntityTypes1_9 {
public static EntityType getTypeFromId(final int typeId, final boolean object) {
EntityType type;
if (object) {
type = ObjectType.getEntityType(typeId);
} else {
type = EntityType.findById(typeId);
}
return type;
}
public enum EntityType implements com.viaversion.viaversion.api.minecraft.entities.EntityType {
ENTITY,
@@ -211,7 +200,13 @@ public class EntityTypes1_9 {
BOAT(1, EntityType.BOAT),
ITEM(2, EntityType.ITEM),
AREA_EFFECT_CLOUD(3, EntityType.AREA_EFFECT_CLOUD),
MINECART(10, EntityType.MINECART), // There are multiple types, but we don't need them
MINECART(10, EntityType.MINECART),
CHEST_MINECART(10, 1, EntityType.CHEST_MINECART),
FURNACE_MINECART(10, 2, EntityType.FURNACE_MINECART),
TNT_MINECART(10, 3, EntityType.TNT_MINECART),
SPAWNER_MINECART(10, 4, EntityType.SPAWNER_MINECART),
HOPPER_MINECART(10, 5, EntityType.HOPPER_MINECART),
COMMAND_BLOCK_MINECART(10, 6, EntityType.COMMAND_BLOCK_MINECART),
TNT_PRIMED(50, EntityType.TNT),
ENDER_CRYSTAL(51, EntityType.END_CRYSTAL),
TIPPED_ARROW(60, EntityType.ARROW),
@@ -234,19 +229,25 @@ public class EntityTypes1_9 {
SPECTRAL_ARROW(91, EntityType.SPECTRAL_ARROW),
DRAGON_FIREBALL(93, EntityType.DRAGON_FIREBALL);
private static final Map<Integer, ObjectType> TYPES = new HashMap<>();
private static final Map<Integer, Map<Integer, ObjectType>> TYPES = new HashMap<>();
private final int id;
private final int data;
private final EntityType type;
static {
for (ObjectType type : ObjectType.values()) {
TYPES.put(type.id, type);
TYPES.computeIfAbsent(type.id, k -> new HashMap<>()).put(type.data, type);
}
}
ObjectType(int id, EntityType type) {
this(id, 0, type);
}
ObjectType(int id, int data, EntityType type) {
this.id = id;
this.data = data;
this.type = type;
}
@@ -255,20 +256,28 @@ public class EntityTypes1_9 {
return id;
}
@Override
public int getData() {
return data;
}
@Override
public EntityType getType() {
return type;
}
public static ObjectType findById(final int id) {
if (id == -1) {
public static ObjectType findById(final int id, final int data) {
final Map<Integer, ObjectType> types = TYPES.get(id);
if (types == null) {
return null;
}
return TYPES.get(id);
final ObjectType type = types.get(data);
return type != null ? type : types.get(0);
}
public static EntityType getEntityType(final int id) {
final ObjectType objectType = findById(id);
public static EntityType getEntityType(final int id, final int data) {
final ObjectType objectType = findById(id, data);
return objectType != null ? objectType.type : null;
}
}
@@ -29,5 +29,7 @@ public interface ObjectType {
int getId();
int getData();
EntityType getType();
}
@@ -0,0 +1,77 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
public final class EntityDataTypes1_21_5 extends AbstractEntityDataTypes {
public final EntityDataType byteType = add(0, Types.BYTE);
public final EntityDataType varIntType = add(1, Types.VAR_INT);
public final EntityDataType longType = add(2, Types.VAR_LONG);
public final EntityDataType floatType = add(3, Types.FLOAT);
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType itemType;
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
public final EntityDataType blockPositionType = add(10, Types.BLOCK_POSITION1_14);
public final EntityDataType optionalBlockPositionType = add(11, Types.OPTIONAL_POSITION_1_14);
public final EntityDataType directionType = add(12, Types.VAR_INT);
public final EntityDataType optionalUUIDType = add(13, Types.OPTIONAL_UUID);
public final EntityDataType blockStateType = add(14, Types.VAR_INT);
public final EntityDataType optionalBlockStateType = add(15, Types.VAR_INT);
public final EntityDataType compoundTagType = add(16, Types.COMPOUND_TAG);
public final EntityDataType particleType;
public final EntityDataType particlesType;
public final EntityDataType villagerDatatType = add(19, Types.VILLAGER_DATA);
public final EntityDataType optionalVarIntType = add(20, Types.OPTIONAL_VAR_INT);
public final EntityDataType poseType = add(21, Types.VAR_INT);
public final EntityDataType catVariantType = add(22, Types.VAR_INT);
public final EntityDataType cowVariantType = add(23, Types.VAR_INT);
public final EntityDataType wolfVariantType = add(24, Types.VAR_INT);
public final EntityDataType wolfSoundVariantType = add(25, Types.VAR_INT);
public final EntityDataType frogVariantType = add(26, Types.VAR_INT);
public final EntityDataType pigVariantType = add(27, Types.VAR_INT);
public final EntityDataType chickenVariantType = add(28, Types.VAR_INT);
public final EntityDataType optionalGlobalPosition = add(29, Types.OPTIONAL_GLOBAL_POSITION);
public final EntityDataType paintingVariantType = add(30, PaintingVariant.TYPE1_21_2);
public final EntityDataType snifferState = add(31, Types.VAR_INT);
public final EntityDataType armadilloState = add(32, Types.VAR_INT);
public final EntityDataType vector3FType = add(33, Types.VECTOR3F);
public final EntityDataType quaternionType = add(34, Types.QUATERNION);
public EntityDataTypes1_21_5(final Type<Item> itemType, final ParticleType particleType, final Type<Particle[]> particlesType) {
super(35);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
}
}
@@ -0,0 +1,42 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.IntSet;
/**
* Item that does not hold any real data outside of its id and amount.
* Instead, it holds hashes of added data and a set of keys of removed data.
* <p>
* This stores the raw int identifiers instead of data keys to simplify handling across protocols
* under the assumption that the keys are almost never needed beyond automated id updating.
*
* @see Item
*/
public interface HashedItem extends ItemBase {
Int2IntMap dataHashesById();
IntSet removedDataIds();
}
@@ -0,0 +1,110 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
public class HashedStructuredItem implements HashedItem {
private final Int2IntMap dataHashes;
private final IntSet removedData;
private int identifier;
private int amount;
public HashedStructuredItem(final int identifier, final int amount) {
this(identifier, amount, new Int2IntOpenHashMap(0), new IntOpenHashSet(0));
}
public HashedStructuredItem(final int identifier, final int amount, final Int2IntMap dataHashes, final IntSet removedData) {
this.identifier = identifier;
this.amount = amount;
this.dataHashes = dataHashes;
this.removedData = removedData;
}
public static HashedStructuredItem empty() {
// Data is mutable, create a new item
return new HashedStructuredItem(0, 0);
}
@Override
public int identifier() {
return this.identifier;
}
@Override
public void setIdentifier(final int identifier) {
this.identifier = identifier;
}
@Override
public int amount() {
return this.amount;
}
@Override
public void setAmount(final int amount) {
this.amount = amount;
}
@Override
public Int2IntMap dataHashesById() {
return this.dataHashes;
}
@Override
public IntSet removedDataIds() {
return this.removedData;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final HashedStructuredItem that = (HashedStructuredItem) o;
if (identifier != that.identifier) return false;
if (amount != that.amount) return false;
return dataHashes.equals(that.dataHashes) && removedData.equals(that.removedData);
}
@Override
public int hashCode() {
int result = dataHashes.hashCode();
result = 31 * result + removedData.hashCode();
result = 31 * result + identifier;
result = 31 * result + amount;
return result;
}
@Override
public String toString() {
return "HashedStructuredItem{" +
"data=Hashes" + dataHashes +
", removedData=" + removedData +
", identifier=" + identifier +
", amount=" + amount +
'}';
}
}
@@ -24,37 +24,10 @@ package com.viaversion.viaversion.api.minecraft.item;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.util.Copyable;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface Item {
/**
* Returns the item identifier.
*
* @return item identifier
*/
int identifier();
/**
* Sets the item identifier.
*
* @param identifier item identifier
*/
void setIdentifier(int identifier);
/**
* Returns the item amount.
*
* @return item amount
*/
int amount();
/**
* Returns the item amount.
*
* @param amount item amount
*/
void setAmount(int amount);
public interface Item extends ItemBase, Copyable {
/**
* Returns the item data. Always 0 for 1.13+ items.
@@ -102,14 +75,6 @@ public interface Item {
*
* @return copy of the item
*/
@Override
Item copy();
/**
* Returns true if the item is empty.
*
* @return true if the item is empty
*/
default boolean isEmpty() {
return identifier() == 0 || amount() <= 0;
}
}
@@ -0,0 +1,67 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
/**
* @see Item
* @see HashedItem
*/
public interface ItemBase {
/**
* Returns the item identifier.
*
* @return item identifier
*/
int identifier();
/**
* Sets the item identifier.
*
* @param identifier item identifier
*/
void setIdentifier(int identifier);
/**
* Returns the item amount.
*
* @return item amount
*/
int amount();
/**
* Returns the item amount.
*
* @param amount item amount
*/
void setAmount(int amount);
/**
* Returns true if the item is empty.
*
* @return true if the item is empty
*/
default boolean isEmpty() {
return identifier() == 0 || amount() <= 0;
}
}
@@ -22,27 +22,54 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record AdventureModePredicate(BlockPredicate[] predicates, boolean showInTooltip) {
public record AdventureModePredicate(BlockPredicate[] predicates, boolean showInTooltip) implements Copyable {
public static final Type<AdventureModePredicate> TYPE = new Type<>(AdventureModePredicate.class) {
public AdventureModePredicate(final BlockPredicate[] predicates) {
this(predicates, true);
}
public static final Type<AdventureModePredicate> TYPE1_20_5 = new Type<>(AdventureModePredicate.class) {
@Override
public AdventureModePredicate read(final ByteBuf buffer) {
final BlockPredicate[] predicates = BlockPredicate.ARRAY_TYPE.read(buffer);
final BlockPredicate[] predicates = BlockPredicate.ARRAY_TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new AdventureModePredicate(predicates, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final AdventureModePredicate value) {
BlockPredicate.ARRAY_TYPE.write(buffer, value.predicates);
BlockPredicate.ARRAY_TYPE1_20_5.write(buffer, value.predicates);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final class AdventureModePredicateType1_21_5 extends Type<AdventureModePredicate> {
private final Type<BlockPredicate[]> blockPredicateType;
public AdventureModePredicateType1_21_5(final Type<StructuredData<?>[]> dataArrayType) {
super(AdventureModePredicate.class);
this.blockPredicateType = new ArrayType<>(new BlockPredicate.BlockPredicateType1_21_5(dataArrayType));
}
@Override
public AdventureModePredicate read(final ByteBuf buffer) {
final BlockPredicate[] predicates = blockPredicateType.read(buffer);
return new AdventureModePredicate(predicates);
}
@Override
public void write(final ByteBuf buffer, final AdventureModePredicate value) {
blockPredicateType.write(buffer, value.predicates);
}
}
public AdventureModePredicate rewrite(final Int2IntFunction blockIdRewriter) {
final BlockPredicate[] predicates = new BlockPredicate[this.predicates.length];
for (int i = 0; i < predicates.length; i++) {
@@ -50,4 +77,9 @@ public record AdventureModePredicate(BlockPredicate[] predicates, boolean showIn
}
return new AdventureModePredicate(predicates, showInTooltip);
}
@Override
public AdventureModePredicate copy() {
return new AdventureModePredicate(copy(predicates), showInTooltip);
}
}
@@ -29,11 +29,15 @@ import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern, boolean showInTooltip) {
public ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern) {
this(material, pattern, true);
}
public static final Type<ArmorTrim> TYPE1_20_5 = new Type<>(ArmorTrim.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_20_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -41,7 +45,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_20_5.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
@@ -49,7 +53,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_2.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -57,7 +61,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_2.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
@@ -65,7 +69,7 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_4.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_20_5.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -73,10 +77,24 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_4.write(buffer, value.material);
ArmorTrimPattern.TYPE.write(buffer, value.pattern);
ArmorTrimPattern.TYPE1_20_5.write(buffer, value.pattern);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<ArmorTrim> TYPE1_21_5 = new Type<>(ArmorTrim.class) {
@Override
public ArmorTrim read(final ByteBuf buffer) {
final Holder<ArmorTrimMaterial> material = ArmorTrimMaterial.TYPE1_21_5.read(buffer);
final Holder<ArmorTrimPattern> pattern = ArmorTrimPattern.TYPE1_21_5.read(buffer);
return new ArmorTrim(material, pattern);
}
@Override
public void write(final ByteBuf buffer, final ArmorTrim value) {
ArmorTrimMaterial.TYPE1_21_5.write(buffer, value.material);
ArmorTrimPattern.TYPE1_21_5.write(buffer, value.pattern);
}
};
public ArmorTrim rewrite(final Int2IntFunction idRewriteFunction) {
Holder<ArmorTrimMaterial> material = this.material;
@@ -25,18 +25,23 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
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) {
Map<String, String> overrideArmorMaterials, Tag description) implements Copyable {
public ArmorTrimMaterial(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) {
this(assetName, 0, 0F, overrideArmorMaterials, description);
}
public static final HolderType<ArmorTrimMaterial> TYPE1_20_5 = new HolderType<>() {
// The override key is an int, but given we don't use it at all and that creating a new type is annoying,
// we'll just store it in the string map:tm:
@@ -47,7 +52,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final int key = Types.VAR_INT.readPrimitive(buffer);
final String value = Types.STRING.read(buffer);
@@ -73,7 +78,6 @@ 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<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
@@ -82,7 +86,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
final float itemModelIndex = buffer.readFloat();
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
@@ -108,7 +112,6 @@ 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<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
@@ -116,7 +119,7 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
final int item = Types.VAR_INT.readPrimitive(buffer);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>(overrideArmorMaterialsSize);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
@@ -141,8 +144,43 @@ 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<>() {
@Override
public ArmorTrimMaterial readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final int overrideArmorMaterialsSize = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> overrideArmorMaterials = new Object2ObjectArrayMap<>();
for (int i = 0; i < overrideArmorMaterialsSize; i++) {
final String key = Types.STRING.read(buffer);
final String value = Types.STRING.read(buffer);
overrideArmorMaterials.put(key, value);
}
final Tag description = Types.TAG.read(buffer);
return new ArmorTrimMaterial(assetName, overrideArmorMaterials, description);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimMaterial value) {
Types.STRING.write(buffer, value.assetName());
Types.VAR_INT.writePrimitive(buffer, value.overrideArmorMaterials().size());
for (final Map.Entry<String, String> entry : value.overrideArmorMaterials().entrySet()) {
Types.STRING.write(buffer, entry.getKey());
Types.STRING.write(buffer, entry.getValue());
}
Types.TAG.write(buffer, value.description());
}
};
public ArmorTrimMaterial rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimMaterial(assetName, idRewriteFunction.applyAsInt(itemId), itemModelIndex, overrideArmorMaterials, description);
}
@Override
public ArmorTrimMaterial copy() {
return new ArmorTrimMaterial(assetName, itemId, itemModelIndex, new Object2ObjectArrayMap<>(overrideArmorMaterials), description);
}
}
@@ -25,12 +25,17 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrimPattern(String assetName, int itemId, Tag description, boolean decal) {
public record ArmorTrimPattern(String assetName, int itemId, Tag description, boolean decal) implements Copyable {
public static final HolderType<ArmorTrimPattern> TYPE = new HolderType<>() {
public ArmorTrimPattern(final String assetName, final Tag description, final boolean decal) {
this(assetName, 0, description, decal);
}
public static final HolderType<ArmorTrimPattern> TYPE1_20_5 = new HolderType<>() {
@Override
public ArmorTrimPattern readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
@@ -48,8 +53,29 @@ public record ArmorTrimPattern(String assetName, int itemId, Tag description, bo
buffer.writeBoolean(value.decal());
}
};
public static final HolderType<ArmorTrimPattern> TYPE1_21_5 = new HolderType<>() {
@Override
public ArmorTrimPattern readDirect(final ByteBuf buffer) {
final String assetName = Types.STRING.read(buffer);
final Tag description = Types.TAG.read(buffer);
final boolean decal = buffer.readBoolean();
return new ArmorTrimPattern(assetName, description, decal);
}
@Override
public void writeDirect(final ByteBuf buffer, final ArmorTrimPattern value) {
Types.STRING.write(buffer, value.assetName());
Types.TAG.write(buffer, value.description());
buffer.writeBoolean(value.decal());
}
};
public ArmorTrimPattern rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimPattern(assetName, idRewriteFunction.applyAsInt(itemId), description, decal);
}
@Override
public ArmorTrimPattern copy() {
return new ArmorTrimPattern(assetName, itemId, description.copy(), decal);
}
}
@@ -25,10 +25,11 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean showInTooltip) {
public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean showInTooltip) implements Copyable {
public static final Type<AttributeModifiers1_20_5> TYPE = new Type<>(AttributeModifiers1_20_5.class) {
@Override
@@ -45,6 +46,11 @@ public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean sh
}
};
@Override
public AttributeModifiers1_20_5 copy() {
return new AttributeModifiers1_20_5(copy(modifiers), showInTooltip);
}
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
@@ -25,12 +25,17 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) {
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) implements Copyable {
public static final Type<AttributeModifiers1_21> TYPE = new Type<>(AttributeModifiers1_21.class) {
public AttributeModifiers1_21(final AttributeModifier[] modifiers) {
this(modifiers, true);
}
public static final Type<AttributeModifiers1_21> TYPE1_21 = new Type<>(AttributeModifiers1_21.class) {
@Override
public AttributeModifiers1_21 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE.read(buffer);
@@ -44,6 +49,18 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
buffer.writeBoolean(value.showInTooltip());
}
};
public static final Type<AttributeModifiers1_21> TYPE1_21_5 = new Type<>(AttributeModifiers1_21.class) {
@Override
public AttributeModifiers1_21 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE.read(buffer);
return new AttributeModifiers1_21(modifiers);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_21 value) {
AttributeModifier.ARRAY_TYPE.write(buffer, value.modifiers());
}
};
public AttributeModifiers1_21 rewrite(final Int2IntFunction rewriteFunction) {
final AttributeModifier[] modifiers = new AttributeModifier[this.modifiers.length];
@@ -54,6 +71,11 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
return new AttributeModifiers1_21(modifiers, showInTooltip);
}
@Override
public AttributeModifiers1_21 copy() {
return new AttributeModifiers1_21(copy(modifiers), showInTooltip);
}
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
@@ -26,9 +26,10 @@ import com.viaversion.nbt.tag.CompoundTag;
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 io.netty.buffer.ByteBuf;
public record Bee(CompoundTag entityData, int ticksInHive, int minTicksInHive) {
public record Bee(CompoundTag entityData, int ticksInHive, int minTicksInHive) implements Copyable {
public static final Type<Bee> TYPE = new Type<>(Bee.class) {
@Override
@@ -48,4 +49,8 @@ public record Bee(CompoundTag entityData, int ticksInHive, int minTicksInHive) {
};
public static final Type<Bee[]> ARRAY_TYPE = new ArrayType<>(TYPE);
@Override
public Bee copy() {
return new Bee(entityData.copy(), ticksInHive, minTicksInHive);
}
}
@@ -24,23 +24,31 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.predicate.DataComponentMatchers;
import com.viaversion.viaversion.api.minecraft.data.predicate.DataComponentMatchers.DataComponentMatchersType;
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 io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher @Nullable [] propertyMatchers,
@Nullable CompoundTag tag) {
@Nullable CompoundTag tag, DataComponentMatchers dataMatchers) implements Copyable {
public static final Type<BlockPredicate> TYPE = new Type<>(BlockPredicate.class) {
public BlockPredicate(@Nullable final HolderSet holderSet, final StatePropertyMatcher @Nullable [] propertyMatchers, @Nullable final CompoundTag tag) {
this(holderSet, propertyMatchers, tag, null);
}
public static final Type<BlockPredicate> TYPE1_20_5 = new Type<>(BlockPredicate.class) {
@Override
public BlockPredicate read(final ByteBuf buffer) {
final HolderSet holders = Types.OPTIONAL_HOLDER_SET.read(buffer);
final StatePropertyMatcher[] propertyMatchers = buffer.readBoolean() ? StatePropertyMatcher.ARRAY_TYPE.read(buffer) : null;
final CompoundTag tag = Types.OPTIONAL_COMPOUND_TAG.read(buffer);
return new BlockPredicate(holders, propertyMatchers, tag);
return new BlockPredicate(holders, propertyMatchers, tag, null);
}
@Override
@@ -55,7 +63,38 @@ public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher
Types.OPTIONAL_COMPOUND_TAG.write(buffer, value.tag);
}
};
public static final Type<BlockPredicate[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public static final Type<BlockPredicate[]> ARRAY_TYPE1_20_5 = new ArrayType<>(TYPE1_20_5);
public static final class BlockPredicateType1_21_5 extends Type<BlockPredicate> {
private final Type<DataComponentMatchers> matchersType;
public BlockPredicateType1_21_5(final Type<StructuredData<?>[]> dataArrayType) {
super(BlockPredicate.class);
this.matchersType = new DataComponentMatchersType(dataArrayType);
}
@Override
public BlockPredicate read(final ByteBuf buffer) {
final HolderSet holders = Types.OPTIONAL_HOLDER_SET.read(buffer);
final StatePropertyMatcher[] propertyMatchers = buffer.readBoolean() ? StatePropertyMatcher.ARRAY_TYPE.read(buffer) : null;
final CompoundTag tag = Types.OPTIONAL_COMPOUND_TAG.read(buffer);
final DataComponentMatchers matchers = matchersType.read(buffer);
return new BlockPredicate(holders, propertyMatchers, tag, matchers);
}
@Override
public void write(final ByteBuf buffer, final BlockPredicate value) {
Types.OPTIONAL_HOLDER_SET.write(buffer, value.holderSet);
buffer.writeBoolean(value.propertyMatchers != null);
if (value.propertyMatchers != null) {
StatePropertyMatcher.ARRAY_TYPE.write(buffer, value.propertyMatchers);
}
Types.OPTIONAL_COMPOUND_TAG.write(buffer, value.tag);
matchersType.write(buffer, value.dataMatchers);
}
}
public BlockPredicate rewrite(final Int2IntFunction blockIdRewriter) {
if (holderSet == null || holderSet.hasTagKey()) {
@@ -65,4 +104,9 @@ public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher
final HolderSet updatedHolders = holderSet.rewrite(blockIdRewriter);
return new BlockPredicate(updatedHolders, propertyMatchers, tag);
}
@Override
public BlockPredicate copy() {
return new BlockPredicate(holderSet, copy(propertyMatchers), tag == null ? null : tag.copy());
}
}
@@ -24,17 +24,18 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import java.util.Map;
public record BlockStateProperties(Map<String, String> properties) {
public record BlockStateProperties(Map<String, String> properties) implements Copyable {
public static final Type<BlockStateProperties> TYPE = new Type<>(BlockStateProperties.class) {
@Override
public BlockStateProperties read(final ByteBuf buffer) {
final int size = Types.VAR_INT.readPrimitive(buffer);
final Map<String, String> properties = new Object2ObjectOpenHashMap<>(size);
final Map<String, String> properties = new Object2ObjectOpenHashMap<>();
for (int i = 0; i < size; i++) {
properties.put(Types.STRING.read(buffer), Types.STRING.read(buffer));
}
@@ -51,4 +52,8 @@ public record BlockStateProperties(Map<String, String> properties) {
}
};
@Override
public BlockStateProperties copy() {
return new BlockStateProperties(new Object2ObjectOpenHashMap<>(properties));
}
}
@@ -0,0 +1,114 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record BlocksAttacks(
float blockDelaySeconds,
float disableCooldownScale,
DamageReduction[] damageReductions,
ItemDamageFunction itemDamage,
@Nullable String bypassedByTag,
@Nullable Holder<SoundEvent> blockSound,
@Nullable Holder<SoundEvent> disableSound
) {
public static final Type<BlocksAttacks> TYPE = new Type<>(BlocksAttacks.class) {
@Override
public BlocksAttacks read(final ByteBuf buffer) {
final float blockDelaySeconds = buffer.readFloat();
final float disableCooldownScale = buffer.readFloat();
final DamageReduction[] damageReductions = DamageReduction.ARRAY_TYPE.read(buffer);
final ItemDamageFunction itemDamage = ItemDamageFunction.TYPE.read(buffer);
final String bypassedByTag = Types.OPTIONAL_STRING.read(buffer);
final Holder<SoundEvent> blockSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
final Holder<SoundEvent> disableSound = Types.OPTIONAL_SOUND_EVENT.read(buffer);
return new BlocksAttacks(blockDelaySeconds, disableCooldownScale, damageReductions, itemDamage, bypassedByTag, blockSound, disableSound);
}
@Override
public void write(final ByteBuf buffer, final BlocksAttacks value) {
buffer.writeFloat(value.blockDelaySeconds());
buffer.writeFloat(value.disableCooldownScale());
DamageReduction.ARRAY_TYPE.write(buffer, value.damageReductions());
ItemDamageFunction.TYPE.write(buffer, value.itemDamage());
Types.OPTIONAL_STRING.write(buffer, value.bypassedByTag());
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.blockSound());
Types.OPTIONAL_SOUND_EVENT.write(buffer, value.disableSound());
}
};
public record DamageReduction(float horizontalBlockingAngle, @Nullable HolderSet type, float base, float factor) {
public static final Type<DamageReduction> TYPE = new Type<>(DamageReduction.class) {
@Override
public DamageReduction read(final ByteBuf buffer) {
final float horizontalBlockingAngle = buffer.readFloat();
final HolderSet type = Types.OPTIONAL_HOLDER_SET.read(buffer);
final float base = buffer.readFloat();
final float factor = buffer.readFloat();
return new DamageReduction(horizontalBlockingAngle, type, base, factor);
}
@Override
public void write(final ByteBuf buffer, final DamageReduction value) {
buffer.writeFloat(value.horizontalBlockingAngle());
Types.OPTIONAL_HOLDER_SET.write(buffer, value.type());
buffer.writeFloat(value.base());
buffer.writeFloat(value.factor());
}
};
public static final ArrayType<DamageReduction> ARRAY_TYPE = new ArrayType<>(TYPE);
}
public record ItemDamageFunction(float threshold, float base, float factor) {
public static final Type<ItemDamageFunction> TYPE = new Type<>(ItemDamageFunction.class) {
@Override
public ItemDamageFunction read(final ByteBuf buffer) {
final float threshold = buffer.readFloat();
final float base = buffer.readFloat();
final float factor = buffer.readFloat();
return new ItemDamageFunction(threshold, base, factor);
}
@Override
public void write(final ByteBuf buffer, final ItemDamageFunction value) {
buffer.writeFloat(value.threshold());
buffer.writeFloat(value.base());
buffer.writeFloat(value.factor());
}
};
}
}
@@ -26,9 +26,10 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration narrationDecoration) {
public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration narrationDecoration) implements Copyable {
public static final HolderType<ChatType> TYPE = new HolderType<>() {
@Override
@@ -45,7 +46,12 @@ public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration nar
}
};
public record ChatTypeDecoration(String translationKey, int[] parameters, Tag style) {
@Override
public ChatType copy() {
return new ChatType(chatDecoration.copy(), narrationDecoration.copy());
}
public record ChatTypeDecoration(String translationKey, int[] parameters, Tag style) implements Copyable {
public static final Type<ChatTypeDecoration> TYPE = new Type<>(ChatTypeDecoration.class) {
@@ -64,5 +70,10 @@ public record ChatType(ChatTypeDecoration chatDecoration, ChatTypeDecoration nar
Types.TAG.write(buffer, value.style());
}
};
@Override
public ChatTypeDecoration copy() {
return new ChatTypeDecoration(translationKey, parameters.clone(), style.copy());
}
}
}
@@ -27,10 +27,12 @@ import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
boolean hasConsumeParticles, ConsumeEffect<?>[] consumeEffects) {
boolean hasConsumeParticles, ConsumeEffect<?>[] consumeEffects) implements Copyable {
public static final Type<?>[] EFFECT_TYPES = {
ApplyStatusEffects.TYPE,
@@ -108,4 +110,14 @@ public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<S
}
};
}
public Consumable1_21_2 rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundHolder = this.sound.updateId(soundIdRewriteFunction);
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, copy(consumeEffects));
}
}
@@ -24,9 +24,10 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[] strings, int[] colors) {
public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[] strings, int[] colors) implements Copyable {
public static final Type<CustomModelData1_21_4> TYPE = new Type<>(CustomModelData1_21_4.class) {
@Override
@@ -46,4 +47,9 @@ public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[]
Types.INT_ARRAY_PRIMITIVE.write(buffer, value.colors());
}
};
@Override
public CustomModelData1_21_4 copy() {
return new CustomModelData1_21_4(copy(floats), copy(booleans), copy(strings), copy(colors));
}
}
@@ -24,10 +24,10 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2.ConsumeEffect;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record DeathProtection(ConsumeEffect<?>[] deathEffects) {
public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyable {
public static final Type<DeathProtection> TYPE = new Type<>(DeathProtection.class) {
@Override
@@ -41,4 +41,9 @@ public record DeathProtection(ConsumeEffect<?>[] deathEffects) {
ConsumeEffect.ARRAY_TYPE.write(buffer, value.deathEffects);
}
};
@Override
public DeathProtection copy() {
return new DeathProtection(copy(deathEffects));
}
}
@@ -27,7 +27,11 @@ import io.netty.buffer.ByteBuf;
public record DyedColor(int rgb, boolean showInTooltip) {
public static final Type<DyedColor> TYPE = new Type<>(DyedColor.class) {
public DyedColor(final int rgb) {
this(rgb, true);
}
public static final Type<DyedColor> TYPE1_20_5 = new Type<>(DyedColor.class) {
@Override
public DyedColor read(final ByteBuf buffer) {
final int rgb = buffer.readInt();
@@ -41,5 +45,16 @@ public record DyedColor(int rgb, boolean showInTooltip) {
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<DyedColor> TYPE1_21_5 = new Type<>(DyedColor.class) {
@Override
public DyedColor read(final ByteBuf buffer) {
final int rgb = buffer.readInt();
return new DyedColor(rgb);
}
@Override
public void write(final ByteBuf buffer, final DyedColor value) {
buffer.writeInt(value.rgb);
}
};
}
@@ -24,13 +24,18 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) {
public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) implements Copyable {
public static final Type<Enchantments> TYPE = new Type<>(Enchantments.class) {
public Enchantments(final Int2IntMap enchantments) {
this(enchantments, true);
}
public static final Type<Enchantments> TYPE1_20_5 = new Type<>(Enchantments.class) {
@Override
public Enchantments read(final ByteBuf buffer) {
final Int2IntMap enchantments = new Int2IntOpenHashMap();
@@ -54,6 +59,29 @@ public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) {
buffer.writeBoolean(value.showInTooltip());
}
};
public static final Type<Enchantments> TYPE1_21_5 = new Type<>(Enchantments.class) {
@Override
public Enchantments read(final ByteBuf buffer) {
final Int2IntMap enchantments = new Int2IntOpenHashMap();
final int size = Types.VAR_INT.readPrimitive(buffer);
for (int i = 0; i < size; i++) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final int level = Types.VAR_INT.readPrimitive(buffer);
enchantments.put(id, level);
}
return new Enchantments(enchantments);
}
@Override
public void write(final ByteBuf buffer, final Enchantments value) {
Types.VAR_INT.writePrimitive(buffer, value.enchantments.size());
for (final Int2IntMap.Entry entry : value.enchantments.int2IntEntrySet()) {
Types.VAR_INT.writePrimitive(buffer, entry.getIntKey());
Types.VAR_INT.writePrimitive(buffer, entry.getIntValue());
}
}
};
public Enchantments(final boolean showInTooltip) {
this(new Int2IntOpenHashMap(), showInTooltip);
@@ -78,4 +106,9 @@ public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) {
public int getLevel(final int id) {
return enchantments.getOrDefault(id, -1);
}
@Override
public Enchantments copy() {
return new Enchantments(new Int2IntOpenHashMap(enchantments), showInTooltip);
}
}
@@ -33,9 +33,14 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Nullable String model,
@Nullable String cameraOverlay, @Nullable HolderSet allowedEntities, boolean dispensable,
boolean swappable, boolean damageOnHurt) {
boolean swappable, boolean damageOnHurt, boolean equipOnInteract) {
public static final Type<Equippable> TYPE = new Type<>(Equippable.class) {
public Equippable(final int equipmentSlot, final Holder<SoundEvent> soundEvent, @Nullable final String model, @Nullable final String cameraOverlay,
@Nullable final HolderSet allowedEntities, final boolean dispensable, final boolean swappable, final boolean damageOnHurt) {
this(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, true);
}
public static final Type<Equippable> TYPE1_21_2 = new Type<>(Equippable.class) {
@Override
public Equippable read(final ByteBuf buffer) {
final int equipmentSlot = Types.VAR_INT.readPrimitive(buffer);
@@ -61,9 +66,37 @@ public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Null
buffer.writeBoolean(value.damageOnHurt());
}
};
public static final Type<Equippable> TYPE1_21_5 = new Type<>(Equippable.class) {
@Override
public Equippable read(final ByteBuf buffer) {
final int equipmentSlot = Types.VAR_INT.readPrimitive(buffer);
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
final String model = Types.OPTIONAL_STRING.read(buffer);
final String cameraOverlay = Types.OPTIONAL_STRING.read(buffer);
final HolderSet allowedEntities = Types.OPTIONAL_HOLDER_SET.read(buffer);
final boolean dispensable = buffer.readBoolean();
final boolean swappable = buffer.readBoolean();
final boolean damageOnHurt = buffer.readBoolean();
final boolean equipOnInteract = buffer.readBoolean();
return new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract);
}
@Override
public void write(final ByteBuf buffer, final Equippable value) {
Types.VAR_INT.writePrimitive(buffer, value.equipmentSlot());
Types.SOUND_EVENT.write(buffer, value.soundEvent());
Types.OPTIONAL_STRING.write(buffer, value.model());
Types.OPTIONAL_STRING.write(buffer, value.cameraOverlay());
Types.OPTIONAL_HOLDER_SET.write(buffer, value.allowedEntities());
buffer.writeBoolean(value.dispensable());
buffer.writeBoolean(value.swappable());
buffer.writeBoolean(value.damageOnHurt());
buffer.writeBoolean(value.equipOnInteract());
}
};
public Equippable rewrite(final Int2IntFunction soundIdRewriter) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriter);
return soundEvent == this.soundEvent ? this : new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
return soundEvent == this.soundEvent ? this : new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract);
}
}
@@ -25,9 +25,10 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boolean hasTrail, boolean hasTwinkle) {
public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boolean hasTrail, boolean hasTwinkle) implements Copyable {
public static final Type<FireworkExplosion> TYPE = new Type<>(FireworkExplosion.class) {
@Override
public FireworkExplosion read(final ByteBuf buffer) {
@@ -50,4 +51,8 @@ public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boole
};
public static final Type<FireworkExplosion[]> ARRAY_TYPE = new ArrayType<>(TYPE);
@Override
public FireworkExplosion copy() {
return new FireworkExplosion(shape, copy(colors), copy(fadeColors), hasTrail, hasTwinkle);
}
}
@@ -24,9 +24,10 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record Fireworks(int flightDuration, FireworkExplosion[] explosions) {
public record Fireworks(int flightDuration, FireworkExplosion[] explosions) implements Copyable {
public static final Type<Fireworks> TYPE = new Type<>(Fireworks.class) {
@Override
@@ -43,4 +44,8 @@ public record Fireworks(int flightDuration, FireworkExplosion[] explosions) {
}
};
@Override
public Fireworks copy() {
return new Fireworks(flightDuration, copy(explosions));
}
}
@@ -27,11 +27,12 @@ import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record FoodProperties1_20_5(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
@Nullable Item usingConvertsTo, FoodEffect[] possibleEffects) {
@Nullable Item usingConvertsTo, FoodEffect[] possibleEffects) implements Copyable {
public static final Type<FoodProperties1_20_5> TYPE1_20_5 = new Type<>(FoodProperties1_20_5.class) {
@Override
@@ -76,6 +77,11 @@ public record FoodProperties1_20_5(int nutrition, float saturationModifier, bool
}
};
@Override
public FoodProperties1_20_5 copy() {
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo == null ? null : usingConvertsTo.copy(), copy(possibleEffects));
}
public record FoodEffect(PotionEffect effect, float probability) {
public static final Type<FoodEffect> TYPE = new Type<>(FoodEffect.class) {
@@ -26,11 +26,13 @@ import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range, Tag description) {
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range, Tag description) implements Copyable {
public static final HolderType<Instrument1_21_2> TYPE = new HolderType<>() {
@Override
@@ -50,9 +52,15 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
Types.TAG.write(buffer, value.description());
}
};
public static final EitherHolderType<Instrument1_21_2> EITHER_HOLDER_TYPE = new EitherHolderType<>(TYPE);
public Instrument1_21_2 rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, description);
}
@Override
public Instrument1_21_2 copy() {
return new Instrument1_21_2(soundEvent, useDuration, range, description.copy());
}
}
@@ -23,46 +23,59 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Either;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record JukeboxPlayable(Either<Holder<JukeboxSong>, String> song, boolean showInTooltip) {
public record JukeboxPlayable(EitherHolder<JukeboxSong> song, boolean showInTooltip) {
public JukeboxPlayable(final Holder<JukeboxSong> song, final boolean showInTooltip) {
this(Either.left(song), showInTooltip);
this(EitherHolder.of(song), showInTooltip);
}
public JukeboxPlayable(final String resourceKey, final boolean showInTooltip) {
this(Either.right(resourceKey), showInTooltip);
this(EitherHolder.of(resourceKey), showInTooltip);
}
public static final Type<JukeboxPlayable> TYPE = new Type<>(JukeboxPlayable.class) {
public static final Type<JukeboxPlayable> TYPE1_21 = new Type<>(JukeboxPlayable.class) {
@Override
public JukeboxPlayable read(final ByteBuf buffer) {
final Either<Holder<JukeboxSong>, String> position = Type.readEither(buffer, JukeboxSong.TYPE, Types.STRING);
final EitherHolder<JukeboxSong> position = EitherHolderType.read(buffer, JukeboxSong.TYPE);
final boolean showInTooltip = buffer.readBoolean();
return new JukeboxPlayable(position, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final JukeboxPlayable value) {
Type.writeEither(buffer, value.song, JukeboxSong.TYPE, Types.STRING);
EitherHolderType.write(buffer, value.song, JukeboxSong.TYPE);
buffer.writeBoolean(value.showInTooltip);
}
};
public static final Type<JukeboxPlayable> TYPE1_21_5 = new Type<>(JukeboxPlayable.class) {
@Override
public JukeboxPlayable read(final ByteBuf buffer) {
final EitherHolder<JukeboxSong> position = EitherHolderType.read(buffer, JukeboxSong.TYPE);
return new JukeboxPlayable(position, true);
}
@Override
public void write(final ByteBuf buffer, final JukeboxPlayable value) {
EitherHolderType.write(buffer, value.song, JukeboxSong.TYPE);
}
};
public JukeboxPlayable rewrite(final Int2IntFunction soundIdRewriteFunction) {
if (song.isRight()) {
if (this.song.hasKey()) {
return this;
}
final Holder<JukeboxSong> songHolder = this.song.left();
final Holder<JukeboxSong> songHolder = this.song.holder();
if (songHolder.hasId()) {
return this;
}
@@ -24,10 +24,11 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public final class PotDecorations {
public final class PotDecorations implements Copyable {
public static final Type<PotDecorations> TYPE = new Type<>(PotDecorations.class) {
@Override
@@ -82,4 +83,9 @@ public final class PotDecorations {
}
return new PotDecorations(newItems);
}
@Override
public PotDecorations copy() {
return new PotDecorations(copy(itemIds));
}
}
@@ -24,11 +24,12 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record PotionContents(@Nullable Integer potion, @Nullable Integer customColor, PotionEffect[] customEffects,
@Nullable String customName) {
@Nullable String customName) implements Copyable {
public PotionContents(final @Nullable Integer potion, final @Nullable Integer customColor, final PotionEffect[] customEffects) {
this(potion, customColor, customEffects, null);
@@ -85,4 +86,9 @@ public record PotionContents(@Nullable Integer potion, @Nullable Integer customC
Types.OPTIONAL_STRING.write(buffer, value.customName);
}
};
@Override
public PotionContents copy() {
return new PotionContents(potion, customColor, copy(customEffects), customName);
}
}
@@ -0,0 +1,56 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ProvidesTrimMaterial(EitherHolder<ArmorTrimMaterial> material) {
public static final Type<ProvidesTrimMaterial> TYPE = new Type<>(ProvidesTrimMaterial.class) {
@Override
public ProvidesTrimMaterial read(final ByteBuf buffer) {
final EitherHolder<ArmorTrimMaterial> position = EitherHolderType.read(buffer, ArmorTrimMaterial.TYPE1_21_5);
return new ProvidesTrimMaterial(position);
}
@Override
public void write(final ByteBuf buffer, final ProvidesTrimMaterial value) {
EitherHolderType.write(buffer, value.material, ArmorTrimMaterial.TYPE1_21_5);
}
};
public ProvidesTrimMaterial rewrite(final Int2IntFunction itemIdRewriter) {
if (material.hasKey() || material.holder().hasId()) {
return this;
}
final ArmorTrimMaterial trimMaterial = material.holder().value();
return new ProvidesTrimMaterial(EitherHolder.of(Holder.of(trimMaterial.rewrite(itemIdRewriter))));
}
}
@@ -27,15 +27,19 @@ import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int damagePerBlock) {
public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int damagePerBlock, boolean canDestroyBlocksInCreative) {
public static final Type<ToolProperties> TYPE = new Type<>(ToolProperties.class) {
public ToolProperties(final ToolRule[] rules, final float defaultMiningSpeed, final int damagePerBlock) {
this(rules, defaultMiningSpeed, damagePerBlock, false);
}
public static final Type<ToolProperties> TYPE1_20_5 = new Type<>(ToolProperties.class) {
@Override
public ToolProperties read(final ByteBuf buffer) {
final ToolRule[] rules = ToolRule.ARRAY_TYPE.read(buffer);
final float defaultMiningSpeed = buffer.readFloat();
final int damagePerBlock = Types.VAR_INT.readPrimitive(buffer);
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock);
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock, true);
}
@Override
@@ -45,12 +49,30 @@ public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int dam
Types.VAR_INT.writePrimitive(buffer, value.damagePerBlock());
}
};
public static final Type<ToolProperties> TYPE1_21_5 = new Type<>(ToolProperties.class) {
@Override
public ToolProperties read(final ByteBuf buffer) {
final ToolRule[] rules = ToolRule.ARRAY_TYPE.read(buffer);
final float defaultMiningSpeed = buffer.readFloat();
final int damagePerBlock = Types.VAR_INT.readPrimitive(buffer);
final boolean canDestroyBlocksInCreative = buffer.readBoolean();
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock, canDestroyBlocksInCreative);
}
@Override
public void write(final ByteBuf buffer, final ToolProperties value) {
ToolRule.ARRAY_TYPE.write(buffer, value.rules());
buffer.writeFloat(value.defaultMiningSpeed());
Types.VAR_INT.writePrimitive(buffer, value.damagePerBlock());
buffer.writeBoolean(value.canDestroyBlocksInCreative());
}
};
public ToolProperties rewrite(final Int2IntFunction blockIdRewriter) {
final ToolRule[] rules = new ToolRule[this.rules.length];
for (int i = 0; i < rules.length; i++) {
rules[i] = this.rules[i].rewrite(blockIdRewriter);
}
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock);
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock, canDestroyBlocksInCreative);
}
}
@@ -0,0 +1,69 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import it.unimi.dsi.fastutil.ints.IntLinkedOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSortedSet;
public record TooltipDisplay(boolean hideTooltip,
IntSortedSet hiddenComponents) { // Keeping the ids raw makes this less annoying to deal with...
public static final Type<TooltipDisplay> TYPE = new Type<>(TooltipDisplay.class) {
@Override
public TooltipDisplay read(final ByteBuf buffer) {
final boolean hideTooltip = buffer.readBoolean();
final IntSortedSet hiddenComponents = new IntLinkedOpenHashSet();
final int size = Types.VAR_INT.readPrimitive(buffer);
for (int i = 0; i < size; i++) {
hiddenComponents.add(Types.VAR_INT.readPrimitive(buffer));
}
return new TooltipDisplay(hideTooltip, hiddenComponents);
}
@Override
public void write(final ByteBuf buffer, final TooltipDisplay value) {
buffer.writeBoolean(value.hideTooltip());
Types.VAR_INT.writePrimitive(buffer, value.hiddenComponents().size());
for (int hiddenComponent : value.hiddenComponents()) {
Types.VAR_INT.writePrimitive(buffer, hiddenComponent);
}
}
};
public TooltipDisplay rewrite(final Int2IntFunction idRewriter) {
if (hiddenComponents.isEmpty()) {
return this;
}
final IntSortedSet newHiddenComponents = new IntLinkedOpenHashSet();
for (final int hiddenComponent : hiddenComponents) {
newHiddenComponents.add(idRewriter.applyAsInt(hiddenComponent));
}
return new TooltipDisplay(hideTooltip, newHiddenComponents);
}
}
@@ -0,0 +1,45 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record Weapon(int itemDamagePerAttack, float disableBlockingForSeconds) {
public static final Type<Weapon> TYPE = new Type<>(Weapon.class) {
@Override
public Weapon read(final ByteBuf buffer) {
final int damagePerAttack = Types.VAR_INT.readPrimitive(buffer);
final float disableBlockingForSeconds = buffer.readFloat();
return new Weapon(damagePerAttack, disableBlockingForSeconds);
}
@Override
public void write(final ByteBuf buffer, final Weapon value) {
Types.VAR_INT.writePrimitive(buffer, value.itemDamagePerAttack());
buffer.writeFloat(value.disableBlockingForSeconds());
}
};
}
@@ -24,10 +24,11 @@ package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record WrittenBook(FilterableString title, String author, int generation, FilterableComponent[] pages,
boolean resolved) {
boolean resolved) implements Copyable {
public static final Type<WrittenBook> TYPE = new Type<>(WrittenBook.class) {
@Override
@@ -50,4 +51,8 @@ public record WrittenBook(FilterableString title, String author, int generation,
}
};
@Override
public WrittenBook copy() {
return new WrittenBook(title, author, generation, copy(pages), resolved);
}
}
@@ -58,7 +58,7 @@ public interface ViaInjector {
* For proxies, this returns the lowest supported protocol version.
*
* @return server protocol version
* @throws Exception if there is an error with getting this info, e.g. not binded
* @throws Exception if there is an error with getting this info, e.g. not bound
* @see ViaPlatform#isProxy()
*/
ProtocolVersion getServerProtocolVersion() throws Exception;
@@ -67,7 +67,7 @@ public interface ViaInjector {
* Returns the supported server protocol versions.
*
* @return server protocol versions
* @throws Exception if there is an error with getting this info, e.g. not binded
* @throws Exception if there is an error with getting this info, e.g. not bound
* @see ViaPlatform#isProxy()
*/
default SortedSet<ProtocolVersion> getServerProtocolVersions() throws Exception {
@@ -24,13 +24,11 @@ package com.viaversion.viaversion.api.platform;
import com.google.gson.JsonObject;
import com.viaversion.viaversion.api.ViaAPI;
import com.viaversion.viaversion.api.command.ViaCommandSender;
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
import com.viaversion.viaversion.api.connection.UserConnection;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.UUID;
import java.util.logging.Logger;
/**
@@ -120,52 +118,36 @@ public interface ViaPlatform<T> {
*/
PlatformTask runRepeatingSync(Runnable runnable, long period);
/**
* Get the online players
*
* @return Array of ViaCommandSender
*/
ViaCommandSender[] getOnlinePlayers();
/**
* Send a message to a player
*
* @param uuid The player's UUID
* @param message The message to send
* @param connection The UserConnection
* @param message The message to send
*/
void sendMessage(UUID uuid, String message);
default void sendMessage(UserConnection connection, String message) {
throw new UnsupportedOperationException("ViaPlatform#sendMessage is not implemented on this platform.");
}
/**
* Kick a player for a reason
*
* @param uuid The player's UUID
* @param message The message to kick them with
* @return True if it was successful
*/
boolean kickPlayer(UUID uuid, String message);
/**
* Disconnects an UserConnection for a reason
*
* @param connection The UserConnection
* @param message The message to kick them with
* @return True if it was successful
*/
default boolean disconnect(UserConnection connection, String message) {
if (connection.isClientSide()) return false;
UUID uuid = connection.getProtocolInfo().getUuid();
if (uuid == null) return false;
return kickPlayer(uuid, message);
default boolean kickPlayer(UserConnection connection, String message) {
throw new UnsupportedOperationException("ViaPlatform#kickPlayer is not implemented on this platform.");
}
/**
* Check if the plugin is enabled.
* Send a custom payload to from a player to the server.
*
* @return True if it is enabled
* @param connection The UserConnection
* @param channel The channel to send the payload on
* @param message The data to send
*/
@Deprecated(forRemoval = true)
default boolean isPluginEnabled() {
return true;
default void sendCustomPayload(UserConnection connection, String channel, byte[] message) {
throw new UnsupportedOperationException("ViaPlatform#sendCustomPayload is not implemented on this platform.");
}
/**
@@ -190,16 +172,21 @@ public interface ViaPlatform<T> {
File getDataFolder();
/**
* Called when a reload happens
* Called when ViaVersion is initialized twice during the same process, this happens on platforms where ViaVersion
* is loaded as a plugin which can be reloaded.
*/
void onReload();
default void onReload() {
}
/**
* Get the JSON data required for /viaversion dump
* Gets optional platform specific data for /viaversion dump. This can be a specific version or a list of installed
* plugins on the platform.
*
* @return The json data
*/
JsonObject getDump();
default JsonObject getDump() {
return new JsonObject();
}
/**
* Returns an immutable collection of classes to be checked as unsupported software with their software name.
@@ -213,7 +213,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
}
/**
* Register the packets for this protocol. To be overriden.
* Register the packets for this protocol. To be overridden.
*/
protected void registerPackets() {
callRegister(getEntityRewriter());
@@ -46,7 +46,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Abstract protocol class handling packet transformation between two protocol versions.
* Clientbound and serverbount packet types can be set to enforce correct usage of them.
* Clientbound and Serverbound packet types can be set to enforce correct usage of them.
*
* @param <CU> unmapped clientbound packet types
* @param <CM> mapped clientbound packet types
@@ -305,7 +305,7 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
* Returns true if this Protocol's {@link #loadMappingData()} method should be called.
* <p>
* This does *not* necessarily mean that {@link #getMappingData()} is non-null, since this may be
* overriden, depending on special cases.
* overridden, depending on special cases.
*
* @return true if this Protocol's {@link #loadMappingData()} method should be called
*/
@@ -34,7 +34,7 @@ public interface PacketMappings {
/**
* Returns a packet mapping for the given packet.
*
* @param state protocol stae
* @param state protocol state
* @param unmappedId unmapped packet id
* @return packet mapping if present
*/
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.protocol.packet.provider;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import java.util.Collection;
import java.util.HashMap;
@@ -65,11 +66,25 @@ public interface PacketTypeMap<P extends PacketType> {
return of(byName, types);
}
static <T extends PacketType> PacketTypeMap<T> of(final Map<String, T> packetsByName, final Int2ObjectMap<T> packetsById) {
return new PacketTypeMapMap<>(packetsByName, packetsById);
static <T extends PacketType, E extends T> PacketTypeMap<T> ofUnsequenced(final Class<E> enumClass) {
final T[] types = enumClass.getEnumConstants();
Preconditions.checkArgument(types != null, "%s is not an enum", enumClass);
final Map<String, T> byName = new HashMap<>(types.length);
for (final T type : types) {
byName.put(type.getName(), type);
}
final Int2ObjectMap<T> byId = new Int2ObjectArrayMap<>();
for (T type : types) {
byId.put(type.getId(), type);
}
return of(byName, byId);
}
static <T extends PacketType> PacketTypeMap<T> of(final Map<String, T> packetsByName, final T[] packets) {
return new PacketTypeArrayMap<>(packetsByName, packets);
}
static <T extends PacketType> PacketTypeMap<T> of(final Map<String, T> packetsByName, final Int2ObjectMap<T> packetsById) {
return new PacketTypeMapMap<>(packetsByName, packetsById);
}
}
@@ -38,7 +38,7 @@ public interface PacketHandler {
/**
* Returns a new packet handler that runs the provided handler after this one.
*
* @param handler packet handler to run aftet this one
* @param handler packet handler to run after this one
* @return a new packet handler that runs the provided handler after this one
*/
default PacketHandler then(final PacketHandler handler) {
@@ -88,6 +88,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
public static final ProtocolVersion v1_21 = register(767, "1.21-1.21.1", new SubVersionRange("1.21", 0, 1));
public static final ProtocolVersion v1_21_2 = register(768, "1.21.2-1.21.3", new SubVersionRange("1.21", 2, 3));
public static final ProtocolVersion v1_21_4 = register(769, "1.21.4");
public static final ProtocolVersion v1_21_5 = register(770, "1.21.5");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -32,4 +32,6 @@ public interface ComponentRewriter {
void processTag(UserConnection connection, @Nullable Tag tag);
void processText(UserConnection connection, @Nullable JsonElement element);
JsonElement processText(UserConnection connection, @Nullable String json);
}
@@ -44,9 +44,10 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
* From 1.14 and onwards, this is the same exact value as {@link #typeFromId(int)}.
*
* @param type entity type id
* @param data entity data
* @return EntityType from id
*/
default EntityType objectTypeFromId(int type) {
default EntityType objectTypeFromId(int type, int data) {
return typeFromId(type);
}
@@ -38,13 +38,13 @@ public abstract class RewriterBase<T extends Protocol<?, ?, ?, ?>> implements Re
}
/**
* To be overriden. Called when registering the rewriter.
* To be overridden. Called when registering the rewriter.
*/
protected void registerPackets() {
}
/**
* To be overriden. Called when registering the rewriter.
* To be overridden. Called when registering the rewriter.
*/
protected void registerRewrites() {
}
@@ -22,9 +22,6 @@
*/
package com.viaversion.viaversion.api.type;
import com.viaversion.viaversion.util.Either;
import io.netty.buffer.ByteBuf;
/**
* Type for buffer reading and writing.
*
@@ -61,7 +58,7 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
* @return type name
*/
public String getTypeName() {
return typeName != null ? typeName : this.getClass().getSimpleName();
return typeName != null && !typeName.isEmpty() ? typeName : this.getClass().getSimpleName();
}
/**
@@ -78,22 +75,4 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public String toString() {
return getTypeName();
}
public static <X, Y> Either<X, Y> readEither(final ByteBuf buf, final Type<X> leftType, final Type<Y> rightType) {
if (buf.readBoolean()) {
return Either.left(leftType.read(buf));
} else {
return Either.right(rightType.read(buf));
}
}
public static <X, Y> void writeEither(final ByteBuf buf, final Either<X, Y> value, final Type<X> leftType, final Type<Y> rightType) {
if (value.isLeft()) {
buf.writeBoolean(true);
leftType.write(buf, value.left());
} else {
buf.writeBoolean(false);
rightType.write(buf, value.right());
}
}
}
@@ -26,12 +26,13 @@ import com.google.gson.JsonElement;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.BlockChangeRecord;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.ChunkPosition;
import com.viaversion.viaversion.api.minecraft.EulerAngle;
import com.viaversion.viaversion.api.minecraft.GameProfile;
import com.viaversion.viaversion.api.minecraft.GlobalBlockPosition;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature;
import com.viaversion.viaversion.api.minecraft.BlockPosition;
import com.viaversion.viaversion.api.minecraft.ProfileKey;
import com.viaversion.viaversion.api.minecraft.Quaternion;
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
@@ -40,9 +41,10 @@ import com.viaversion.viaversion.api.minecraft.Vector;
import com.viaversion.viaversion.api.minecraft.Vector3f;
import com.viaversion.viaversion.api.minecraft.VillagerData;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.chunks.Heightmap;
import com.viaversion.viaversion.api.minecraft.item.HashedItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.api.minecraft.ChunkPosition;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.BitSetType;
import com.viaversion.viaversion.api.type.types.BooleanArrayType;
@@ -74,6 +76,8 @@ import com.viaversion.viaversion.api.type.types.block.BlockChangeRecordType;
import com.viaversion.viaversion.api.type.types.block.BlockEntityType1_18;
import com.viaversion.viaversion.api.type.types.block.BlockEntityType1_20_2;
import com.viaversion.viaversion.api.type.types.block.VarLongBlockChangeRecordType;
import com.viaversion.viaversion.api.type.types.chunk.HeightmapType;
import com.viaversion.viaversion.api.type.types.item.HashedItemType1_21_5;
import com.viaversion.viaversion.api.type.types.item.ItemShortArrayType1_13;
import com.viaversion.viaversion.api.type.types.item.ItemShortArrayType1_13_2;
import com.viaversion.viaversion.api.type.types.item.ItemShortArrayType1_8;
@@ -81,11 +85,11 @@ import com.viaversion.viaversion.api.type.types.item.ItemType1_13;
import com.viaversion.viaversion.api.type.types.item.ItemType1_13_2;
import com.viaversion.viaversion.api.type.types.item.ItemType1_20_2;
import com.viaversion.viaversion.api.type.types.item.ItemType1_8;
import com.viaversion.viaversion.api.type.types.math.BlockPositionType1_14;
import com.viaversion.viaversion.api.type.types.math.BlockPositionType1_8;
import com.viaversion.viaversion.api.type.types.math.ChunkPositionType;
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.BlockPositionType1_14;
import com.viaversion.viaversion.api.type.types.math.BlockPositionType1_8;
import com.viaversion.viaversion.api.type.types.math.QuaternionType;
import com.viaversion.viaversion.api.type.types.math.Vector3fType;
import com.viaversion.viaversion.api.type.types.math.VectorType;
@@ -131,6 +135,7 @@ public final class Types {
public static final DoubleType DOUBLE = new DoubleType();
public static final LongType LONG = new LongType();
public static final Type<Long> OPTIONAL_LONG = new LongType.OptionalLongType();
public static final Type<long[]> LONG_ARRAY_PRIMITIVE = new LongArrayType();
public static final BooleanType BOOLEAN = new BooleanType();
@@ -212,7 +217,12 @@ public final class Types {
public static final Type<HolderSet> OPTIONAL_HOLDER_SET = new HolderSetType.OptionalHolderSetType();
public static final HolderType<SoundEvent> SOUND_EVENT = new SoundEventType();
public static final HolderType<SoundEvent> OPTIONAL_SOUND_EVENT = new SoundEventType.OptionalSoundEventType();
public static final Type<Heightmap> HEIGHTMAP = new HeightmapType();
public static final Type<Heightmap[]> HEIGHTMAP_ARRAY = new ArrayType<>(HEIGHTMAP);
// 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();
public static final Type<Item> ITEM1_13_2 = new ItemType1_13_2();
@@ -223,4 +233,6 @@ public final class Types {
public static final Type<Item[]> ITEM1_13_ARRAY = new ArrayType<>(ITEM1_13);
public static final Type<Item[]> ITEM1_13_2_ARRAY = new ArrayType<>(ITEM1_13_2);
public static final Type<Item[]> ITEM1_20_2_ARRAY = new ArrayType<>(ITEM1_20_2);
public static final Type<HashedItem> HASHED_ITEM = new HashedItemType1_21_5();
}
@@ -0,0 +1,67 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Either;
import io.netty.buffer.ByteBuf;
// Yuck - only use when necessary
public final class EitherType<T, V> extends Type<Either<T, V>> {
private final Type<T> leftType;
private final Type<V> rightType;
public EitherType(final Type<T> leftType, final Type<V> rightType) {
super(Either.class);
this.leftType = leftType;
this.rightType = rightType;
}
@Override
public Either<T, V> read(final ByteBuf buffer) {
return read(buffer, this.leftType, this.rightType);
}
@Override
public void write(final ByteBuf buffer, final Either<T, V> value) {
write(buffer, value, this.leftType, this.rightType);
}
public static <X, Y> Either<X, Y> read(final ByteBuf buf, final Type<X> leftType, final Type<Y> rightType) {
if (buf.readBoolean()) {
return Either.left(leftType.read(buf));
} else {
return Either.right(rightType.read(buf));
}
}
public static <X, Y> void write(final ByteBuf buf, final Either<X, Y> value, final Type<X> leftType, final Type<Y> rightType) {
if (value.isLeft()) {
buf.writeBoolean(true);
leftType.write(buf, value.left());
} else {
buf.writeBoolean(false);
rightType.write(buf, value.right());
}
}
}
@@ -22,30 +22,51 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public class LongArrayType extends Type<long[]> {
public LongArrayType() {
private final int length;
public LongArrayType(final int length) {
super(long[].class);
this.length = length;
}
public LongArrayType() {
this(-1);
}
@Override
public long[] read(ByteBuf buffer) {
int length = Types.VAR_INT.readPrimitive(buffer);
long[] array = new long[length];
for (int i = 0; i < array.length; i++) {
array[i] = buffer.readLong();
public long[] read(final ByteBuf buffer) {
final int length = this.length == -1 ? Types.VAR_INT.readPrimitive(buffer) : this.length;
Preconditions.checkArgument(buffer.isReadable(length), "Length is fewer than readable bytes");
return readFixedLength(buffer, length);
}
public static long[] readFixedLength(final ByteBuf buffer, final int expectedLength) {
final long[] value = new long[expectedLength];
for (int i = 0; i < expectedLength; i++) {
value[i] = buffer.readLong();
}
return array;
return value;
}
@Override
public void write(ByteBuf buffer, long[] object) {
Types.VAR_INT.writePrimitive(buffer, object.length);
for (long l : object) {
public void write(final ByteBuf buffer, final long[] object) {
if (this.length != -1) {
Preconditions.checkArgument(length == object.length, "Length does not match expected length");
} else {
Types.VAR_INT.writePrimitive(buffer, object.length);
}
writeFixedLength(buffer, object);
}
public static void writeFixedLength(final ByteBuf buffer, final long[] object) {
for (final long l : object) {
buffer.writeLong(l);
}
}
@@ -22,8 +22,10 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.TypeConverter;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public class LongType extends Type<Long> implements TypeConverter<Long> {
@@ -67,4 +69,11 @@ public class LongType extends Type<Long> implements TypeConverter<Long> {
public void writePrimitive(ByteBuf buffer, long object) {
buffer.writeLong(object);
}
public static final class OptionalLongType extends OptionalType<Long> {
public OptionalLongType() {
super(Types.LONG);
}
}
}
@@ -25,14 +25,15 @@ package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionImpl;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
public final class ChunkSectionType1_18 extends Type<ChunkSection> {
public class ChunkSectionType1_18 extends Type<ChunkSection> {
private final PaletteType1_18 blockPaletteType;
private final PaletteType1_18 biomePaletteType;
private final PaletteTypeBase blockPaletteType;
private final PaletteTypeBase biomePaletteType;
public ChunkSectionType1_18(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(ChunkSection.class);
@@ -40,6 +41,12 @@ public final class ChunkSectionType1_18 extends Type<ChunkSection> {
this.biomePaletteType = new PaletteType1_18(PaletteType.BIOMES, globalPaletteBiomeBits);
}
protected ChunkSectionType1_18(final PaletteTypeBase blockPaletteType, PaletteTypeBase biomePaletteType) {
super(ChunkSection.class);
this.blockPaletteType = blockPaletteType;
this.biomePaletteType = biomePaletteType;
}
@Override
public ChunkSection read(final ByteBuf buffer) {
final ChunkSection chunkSection = new ChunkSectionImpl();
@@ -0,0 +1,35 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
public class ChunkSectionType1_21_5 extends ChunkSectionType1_18 {
public ChunkSectionType1_21_5(final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(
new PaletteType1_21_5(PaletteType.BLOCKS, globalPaletteBlockBits),
new PaletteType1_21_5(PaletteType.BIOMES, globalPaletteBiomeBits)
);
}
}
@@ -0,0 +1,88 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.minecraft.blockentity.BlockEntity;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk1_21_5;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.Heightmap;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class ChunkType1_21_5 extends Type<Chunk> {
private final ChunkSectionType1_18 sectionType;
private final int ySectionCount;
public ChunkType1_21_5(final int ySectionCount, final int globalPaletteBlockBits, final int globalPaletteBiomeBits) {
super(Chunk.class);
Preconditions.checkArgument(ySectionCount > 0);
this.sectionType = new ChunkSectionType1_21_5(globalPaletteBlockBits, globalPaletteBiomeBits);
this.ySectionCount = ySectionCount;
}
@Override
public Chunk read(final ByteBuf buffer) {
final int chunkX = buffer.readInt();
final int chunkZ = buffer.readInt();
final Heightmap[] heightmaps = Types.HEIGHTMAP_ARRAY.read(buffer);
// Read sections
final ByteBuf sectionsBuf = buffer.readSlice(Types.VAR_INT.readPrimitive(buffer));
final ChunkSection[] sections = new ChunkSection[ySectionCount];
for (int i = 0; i < ySectionCount; i++) {
sections[i] = sectionType.read(sectionsBuf);
}
final int blockEntitiesLength = Types.VAR_INT.readPrimitive(buffer);
final List<BlockEntity> blockEntities = new ArrayList<>(blockEntitiesLength);
for (int i = 0; i < blockEntitiesLength; i++) {
blockEntities.add(Types.BLOCK_ENTITY1_20_2.read(buffer));
}
return new Chunk1_21_5(chunkX, chunkZ, sections, heightmaps, blockEntities);
}
@Override
public void write(final ByteBuf buffer, final Chunk chunk) {
buffer.writeInt(chunk.getX());
buffer.writeInt(chunk.getZ());
Types.HEIGHTMAP_ARRAY.write(buffer, chunk.heightmaps());
Types.VAR_INT.writePrimitive(buffer, sectionType.serializedSize(chunk));
for (final ChunkSection section : chunk.getSections()) {
sectionType.write(buffer, section);
}
Types.VAR_INT.writePrimitive(buffer, chunk.blockEntities().size());
for (final BlockEntity blockEntity : chunk.blockEntities()) {
Types.BLOCK_ENTITY1_20_2.write(buffer, blockEntity);
}
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.Heightmap;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public final class HeightmapType extends Type<Heightmap> {
public HeightmapType() {
super(Heightmap.class);
}
@Override
public Heightmap read(final ByteBuf buffer) {
final int type = Types.VAR_INT.readPrimitive(buffer);
final long[] data = Types.LONG_ARRAY_PRIMITIVE.read(buffer);
return new Heightmap(type, data);
}
@Override
public void write(final ByteBuf buffer, final Heightmap value) {
Types.VAR_INT.writePrimitive(buffer, value.type());
Types.LONG_ARRAY_PRIMITIVE.write(buffer, value.data());
}
}
@@ -25,19 +25,17 @@ package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.DataPaletteImpl;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.VarIntType;
import com.viaversion.viaversion.util.CompactArrayUtil;
import com.viaversion.viaversion.util.MathUtil;
import io.netty.buffer.ByteBuf;
public final class PaletteType1_18 extends Type<DataPalette> {
private final int globalPaletteBits;
private final PaletteType type;
public class PaletteType1_18 extends PaletteTypeBase {
protected final int globalPaletteBits;
protected final PaletteType type;
public PaletteType1_18(final PaletteType type, final int globalPaletteBits) {
super(DataPalette.class);
this.globalPaletteBits = globalPaletteBits;
this.type = type;
}
@@ -50,7 +48,7 @@ public final class PaletteType1_18 extends Type<DataPalette> {
// Single value storage
palette = new DataPaletteImpl(type.size(), 1);
palette.addId(Types.VAR_INT.readPrimitive(buffer));
Types.LONG_ARRAY_PRIMITIVE.read(buffer); // Just eat it if not empty - thanks, Hypixel
readValues(buffer, 0, palette); // Just eat it if not empty - thanks, Hypixel
return palette;
}
@@ -72,6 +70,11 @@ public final class PaletteType1_18 extends Type<DataPalette> {
}
// Read values
readValues(buffer, bitsPerValue, palette);
return palette;
}
protected void readValues(final ByteBuf buffer, final int bitsPerValue, final DataPaletteImpl palette) {
final long[] values = Types.LONG_ARRAY_PRIMITIVE.read(buffer);
if (values.length > 0) {
final int valuesPerLong = (char) (64 / bitsPerValue);
@@ -81,7 +84,6 @@ public final class PaletteType1_18 extends Type<DataPalette> {
bitsPerValue == globalPaletteBits ? palette::setIdAt : palette::setPaletteIndexAt);
}
}
return palette;
}
@Override
@@ -91,7 +93,7 @@ public final class PaletteType1_18 extends Type<DataPalette> {
// Single value palette
buffer.writeByte(0); // 0 bit storage
Types.VAR_INT.writePrimitive(buffer, palette.idByIndex(0));
Types.VAR_INT.writePrimitive(buffer, 0); // Empty values length
writeValues(buffer, palette, 0);
return;
}
@@ -106,7 +108,22 @@ public final class PaletteType1_18 extends Type<DataPalette> {
}
}
Types.LONG_ARRAY_PRIMITIVE.write(buffer, CompactArrayUtil.createCompactArrayWithPadding(bitsPerValue, type.size(), bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt));
writeValues(buffer, palette, bitsPerValue);
}
protected void writeValues(final ByteBuf buffer, final DataPalette palette, final int bitsPerValue) {
if (bitsPerValue == 0) {
// Single value storage with the first palette entry
Types.VAR_INT.writePrimitive(buffer, 0);
return;
}
final long[] values = CompactArrayUtil.createCompactArrayWithPadding(
bitsPerValue,
type.size(),
bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt
);
Types.LONG_ARRAY_PRIMITIVE.write(buffer, values);
}
private int bitsPerValue(final int size) {
@@ -119,15 +136,17 @@ public final class PaletteType1_18 extends Type<DataPalette> {
return bitsPerValue;
}
@Override
public int serializedSize(final DataPalette palette) {
// This is a bit of extra work, but worth it to avoid otherwise having to allocate and write to an extra buffer.
// On top of saving memory, it provides small but measurable speedup compared to writing to a separate buffer and then back
final int size = palette.size();
final int bitsPerValue = bitsPerValue(size);
final int serializedValuesSize;
int serializedTypesSize = 0;
int serializedValuesSize = 1; // At least one byte for 0 length
if (size == 1) {
serializedTypesSize = VarIntType.varIntLength(palette.idByIndex(0));
serializedValuesSize = serializedValuesSize(0);
} else {
if (bitsPerValue != globalPaletteBits) {
serializedTypesSize = VarIntType.varIntLength(size);
@@ -138,9 +157,13 @@ public final class PaletteType1_18 extends Type<DataPalette> {
final int valuesPerLong = 64 / bitsPerValue;
final int values = (type.size() + valuesPerLong - 1) / valuesPerLong;
serializedValuesSize = VarIntType.varIntLength(values) + (Long.BYTES * values);
serializedValuesSize = serializedValuesSize(values);
}
return Byte.BYTES + serializedTypesSize + serializedValuesSize;
}
protected int serializedValuesSize(final int values) {
return VarIntType.varIntLength(values) + (Long.BYTES * values);
}
}
@@ -0,0 +1,76 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.minecraft.chunks.DataPaletteImpl;
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
import com.viaversion.viaversion.api.type.types.LongArrayType;
import com.viaversion.viaversion.util.CompactArrayUtil;
import io.netty.buffer.ByteBuf;
// Values are written without the explicit length, as the length is always known
public final class PaletteType1_21_5 extends PaletteType1_18 {
public PaletteType1_21_5(final PaletteType type, final int globalPaletteBits) {
super(type, globalPaletteBits);
}
@Override
protected void readValues(final ByteBuf buffer, final int bitsPerValue, final DataPaletteImpl palette) {
if (bitsPerValue == 0) {
return;
}
final int valuesPerLong = (char) (64 / bitsPerValue);
final int expectedLength = (type.size() + valuesPerLong - 1) / valuesPerLong;
final long[] values = LongArrayType.readFixedLength(buffer, expectedLength);
if (values.length != 0) {
CompactArrayUtil.iterateCompactArrayWithPadding(
bitsPerValue,
type.size(),
values,
bitsPerValue == globalPaletteBits ? palette::setIdAt : palette::setPaletteIndexAt
);
}
}
@Override
protected void writeValues(final ByteBuf buffer, final DataPalette palette, final int bitsPerValue) {
if (bitsPerValue == 0) {
return;
}
final long[] values = CompactArrayUtil.createCompactArrayWithPadding(
bitsPerValue,
type.size(),
bitsPerValue == globalPaletteBits ? palette::idAt : palette::paletteIndexAt
);
LongArrayType.writeFixedLength(buffer, values);
}
@Override
protected int serializedValuesSize(final int values) {
return Long.BYTES * values;
}
}
@@ -0,0 +1,42 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.chunk;
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
import com.viaversion.viaversion.api.type.Type;
import org.checkerframework.checker.nullness.qual.Nullable;
public abstract class PaletteTypeBase extends Type<DataPalette> {
protected PaletteTypeBase() {
super(DataPalette.class);
}
/**
* Calculates the size of the serialized data in bytes.
*
* @param palette data palette
* @return the size of the serialized data in bytes
*/
public abstract int serializedSize(@Nullable DataPalette palette);
}
@@ -0,0 +1,90 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.item;
import com.viaversion.viaversion.api.minecraft.item.HashedItem;
import com.viaversion.viaversion.api.minecraft.item.HashedStructuredItem;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Limit;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
public class HashedItemType1_21_5 extends Type<HashedItem> {
public HashedItemType1_21_5() {
super(HashedItem.class);
}
@Override
public HashedItem read(final ByteBuf buffer) {
if (!buffer.readBoolean()) {
return HashedStructuredItem.empty();
}
final int id = Types.VAR_INT.readPrimitive(buffer);
final int amount = Types.VAR_INT.readPrimitive(buffer);
final int addedComponentsSize = Limit.max(Types.VAR_INT.readPrimitive(buffer), 256);
final Int2IntMap dataHashes = new Int2IntOpenHashMap(addedComponentsSize);
for (int i = 0; i < addedComponentsSize; i++) {
final int dataType = Types.VAR_INT.readPrimitive(buffer);
final int hash = Types.INT.readPrimitive(buffer);
dataHashes.put(dataType, hash);
}
final int removedComponentsSize = Limit.max(Types.VAR_INT.readPrimitive(buffer), 256);
final IntSet removedData = new IntOpenHashSet(removedComponentsSize);
for (int i = 0; i < removedComponentsSize; i++) {
final int dataType = Types.VAR_INT.readPrimitive(buffer);
removedData.add(dataType);
}
return new HashedStructuredItem(id, amount, dataHashes, removedData);
}
@Override
public void write(final ByteBuf buffer, final HashedItem value) {
if (value.isEmpty()) {
buffer.writeBoolean(false);
return;
}
buffer.writeBoolean(true);
Types.VAR_INT.writePrimitive(buffer, value.identifier());
Types.VAR_INT.writePrimitive(buffer, value.amount());
Types.VAR_INT.writePrimitive(buffer, value.dataHashesById().size());
for (final Int2IntMap.Entry entry : value.dataHashesById().int2IntEntrySet()) {
Types.VAR_INT.writePrimitive(buffer, entry.getIntKey());
Types.INT.writePrimitive(buffer, entry.getIntValue());
}
Types.VAR_INT.writePrimitive(buffer, value.removedDataIds().size());
for (final int removedDataId : value.removedDataIds()) {
Types.VAR_INT.writePrimitive(buffer, removedDataId);
}
}
}
@@ -37,9 +37,9 @@ import java.util.Map;
public class ItemType1_20_5 extends Type<Item> {
private final StructuredDataType dataType;
private final StructuredDataTypeBase dataType;
public ItemType1_20_5(final StructuredDataType dataType) {
public ItemType1_20_5(final StructuredDataTypeBase dataType) {
super(Item.class);
this.dataType = dataType;
}
@@ -60,7 +60,7 @@ public class ItemType1_20_5 extends Type<Item> {
final int valuesSize = Types.VAR_INT.readPrimitive(buffer);
final int markersSize = Types.VAR_INT.readPrimitive(buffer);
if (valuesSize == 0 && markersSize == 0) {
return new Reference2ObjectOpenHashMap<>();
return new Reference2ObjectOpenHashMap<>(0);
}
final Map<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>(Math.min(valuesSize + markersSize, 128));
@@ -0,0 +1,76 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.item;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
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;
/**
* Wraps a data component codec, where data components are prefixed with their byte size (used in creative mode packets).
*/
public class LengthPrefixedStructuredDataType extends Type<StructuredData<?>> implements StructuredDataTypeBase {
private final StructuredDataType wrapped;
public LengthPrefixedStructuredDataType(final StructuredDataType dataType) {
super(StructuredData.class);
this.wrapped = dataType;
}
@Override
public void write(final ByteBuf buffer, final StructuredData<?> value) {
Types.VAR_INT.writePrimitive(buffer, value.id());
// Same deal as with chunk data, except pre-calculating the size would be madness
final ByteBuf tempBuf = buffer.alloc().buffer();
try {
value.write(tempBuf);
Types.VAR_INT.writePrimitive(buffer, tempBuf.readableBytes());
buffer.writeBytes(tempBuf);
} finally {
tempBuf.release();
}
}
@Override
public StructuredData<?> read(final ByteBuf buffer) {
final int id = Types.VAR_INT.readPrimitive(buffer);
final StructuredDataKey<?> key = key(id);
if (key == null) {
throw new IllegalArgumentException("No data component serializer found for id " + id);
}
final int size = Types.VAR_INT.readPrimitive(buffer);
final ByteBuf slicedBuf = buffer.readSlice(size);
return wrapped.readData(slicedBuf, key, id);
}
@Override
public @Nullable StructuredDataKey<?> key(final int id) {
return wrapped.key(id);
}
}
@@ -32,7 +32,7 @@ import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public class StructuredDataType extends Type<StructuredData<?>> {
public class StructuredDataType extends Type<StructuredData<?>> implements StructuredDataTypeBase {
private StructuredDataKey<?>[] types;
@@ -57,11 +57,12 @@ public class StructuredDataType extends Type<StructuredData<?>> {
return readData(buffer, key, id);
}
@Override
public @Nullable StructuredDataKey<?> key(final int id) {
return id >= 0 && id < types.length ? types[id] : null;
}
private <T> StructuredData<T> readData(final ByteBuf buffer, final StructuredDataKey<T> key, final int id) {
<T> StructuredData<T> readData(final ByteBuf buffer, final StructuredDataKey<T> key, final int id) {
return StructuredData.of(key, key.type().read(buffer), id);
}
@@ -0,0 +1,37 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.item;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface StructuredDataTypeBase {
StructuredData<?> read(ByteBuf buffer);
void write(ByteBuf buffer, StructuredData<?> value);
@Nullable StructuredDataKey<?> key(int id);
}
@@ -0,0 +1,64 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.misc;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public final class EitherHolderType<T> extends Type<EitherHolder<T>> {
private final HolderType<T> holderType;
public EitherHolderType(final HolderType<T> holderType) {
super(EitherHolder.class);
this.holderType = holderType;
}
@Override
public EitherHolder<T> read(final ByteBuf buffer) {
return read(buffer, this.holderType);
}
@Override
public void write(final ByteBuf buffer, final EitherHolder<T> object) {
write(buffer, object, this.holderType);
}
public static <T> EitherHolder<T> read(final ByteBuf buffer, final HolderType<T> holderType) {
if (buffer.readBoolean()) {
return EitherHolder.of(holderType.read(buffer));
}
return EitherHolder.of(Types.STRING.read(buffer));
}
public static <T> void write(final ByteBuf buffer, final EitherHolder<T> object, final HolderType<T> holderType) {
if (object.hasHolder()) {
buffer.writeBoolean(true);
holderType.write(buffer, object.holder());
} else {
buffer.writeBoolean(false);
Types.STRING.write(buffer, object.key());
}
}
}
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.minecraft.Holder;
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 abstract class HolderType<T> extends Type<Holder<T>> {
@@ -55,4 +56,37 @@ public abstract class HolderType<T> extends Type<Holder<T>> {
public abstract T readDirect(final ByteBuf buffer);
public abstract void writeDirect(final ByteBuf buffer, final T object);
public abstract static class OptionalHolderType<T> extends HolderType<T> {
private final HolderType<T> type;
protected OptionalHolderType(final HolderType<T> type) {
this.type = type;
}
@Override
public Holder<T> read(final ByteBuf buffer) {
return buffer.readBoolean() ? super.read(buffer) : null;
}
@Override
public void write(final ByteBuf buffer, final Holder<T> object) {
if (object != null) {
buffer.writeBoolean(true);
super.write(buffer, object);
} else {
buffer.writeBoolean(false);
}
}
@Override
public @Nullable T readDirect(ByteBuf buffer) {
return this.type.readDirect(buffer);
}
@Override
public void writeDirect(final ByteBuf buffer, @Nullable final T value) {
this.type.writeDirect(buffer, value);
}
}
}
@@ -40,4 +40,11 @@ public final class SoundEventType extends HolderType<SoundEvent> {
Types.STRING.write(buffer, value.identifier());
Types.OPTIONAL_FLOAT.write(buffer, value.fixedRange());
}
public static final class OptionalSoundEventType extends OptionalHolderType<SoundEvent> {
public OptionalSoundEventType() {
super(Types.SOUND_EVENT);
}
}
}
@@ -25,6 +25,7 @@ package com.viaversion.viaversion.api.type.types.misc;
import com.viaversion.nbt.io.TagRegistry;
import com.viaversion.nbt.limiter.TagLimiter;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
@@ -49,7 +50,11 @@ public class TagType extends Type<Tag> {
try {
return TagRegistry.read(id, new ByteBufInputStream(buffer), tagLimiter, 0);
} catch (final IOException e) {
throw new RuntimeException(e);
if (Via.getManager().isDebug()) {
throw new RuntimeException(e);
} else {
throw new RuntimeException("Error reading tag :" + e.getMessage());
}
}
}
@@ -0,0 +1,58 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type.types.version;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21_5;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.types.item.ItemCostType1_20_5;
import com.viaversion.viaversion.api.type.types.item.ItemType1_20_5;
import com.viaversion.viaversion.api.type.types.item.LengthPrefixedStructuredDataType;
import com.viaversion.viaversion.api.type.types.item.StructuredDataType;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import java.util.List;
// Most of these are only safe to use after protocol loading
public final class Types1_21_5 {
public static final StructuredDataType STRUCTURED_DATA = new StructuredDataType();
public static final LengthPrefixedStructuredDataType LENGTH_PREFIXED_STRUCTURED_DATA = new LengthPrefixedStructuredDataType(STRUCTURED_DATA);
public static final Type<StructuredData<?>[]> STRUCTURED_DATA_ARRAY = new ArrayType<>(STRUCTURED_DATA);
public static final ItemType1_20_5 ITEM = new ItemType1_20_5(STRUCTURED_DATA);
public static final ItemType1_20_5 LENGTH_PREFIXED_ITEM = new ItemType1_20_5(LENGTH_PREFIXED_STRUCTURED_DATA);
public static final Type<Item[]> ITEM_ARRAY = new ArrayType<>(ITEM);
public static final Type<Item> ITEM_COST = new ItemCostType1_20_5(STRUCTURED_DATA_ARRAY);
public static final Type<Item> OPTIONAL_ITEM_COST = new ItemCostType1_20_5.OptionalItemCostType(ITEM_COST);
public static final ParticleType PARTICLE = new ParticleType();
public static final ArrayType<Particle> PARTICLES = new ArrayType<>(PARTICLE);
public static final EntityDataTypes1_21_5 ENTITY_DATA_TYPES = new EntityDataTypes1_21_5(ITEM, PARTICLE, PARTICLES);
public static final Type<EntityData> ENTITY_DATA = new EntityDataType(ENTITY_DATA_TYPES);
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
}
@@ -56,7 +56,7 @@ public class CancelDecoderException extends DecoderException implements CancelCo
/**
* Returns a cached CancelDecoderException or a new instance when {@link ViaManager#isDebug()} is true.
*
* @param cause cause for being used when a new instance is creeated
* @param cause cause for being used when a new instance is created
* @return a CancelDecoderException instance
*/
public static CancelDecoderException generate(Throwable cause) {
Loaded 100 of 217 files, more files were not shown because too many files have changed in this diff. Show more