Compare commits

..
99 Commits
Author SHA1 Message Date
Nassim Jahnke 351b42b5e5 5.4.1 Release 2025-06-30 09:56:25 +02:00
Nassim Jahnke 20e3c832fb 1.21.7-rc2 2025-06-30 09:49:48 +02:00
Nassim Jahnke ec9c121da2 1.21.7-rc1 2025-06-30 09:49:47 +02:00
FlorianMichael 12c773edea Add missing translatable mappings (#4542)
Fixes #3331
Fixes #4273
2025-06-30 09:47:33 +02:00
Nassim Jahnke 97b411aa6d Manually handle text component boolean entries
Fixes #4558
2025-06-29 16:36:12 +02:00
Nassim Jahnke 24f6c4f0fd Implement hashing for potion contents 2025-06-29 15:50:56 +02:00
FlorianMichael 9409c7d22a [ci skip] Add SECURITY.md (#4520) 2025-06-29 15:36:49 +02:00
FlorianMichael 17d94a17f0 Always write length in LengthPrefixedTagType 2025-06-29 11:51:38 +02:00
riku6460andFlorianMichael a1cb4d3691 Add Types#CUSTOM_CLICK_ACTION_TAG for VB (#4557)
* Add LengthPrefixedTagType for CUSTOM_CLICK_ACTION

* Move type into own class, add instance into Types

---------

Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-06-29 07:21:48 +02:00
Nassim Jahnke 1d5070a480 Allow mapping sound event holders to empty sounds 2025-06-27 10:24:34 +02:00
FlorianMichaelanddewgs f612adbd0a Rewrite player & display name in player info packet in 1.12.2->1.13 (#4550)
Fixes Tablist plugins on some servers breaking since the game profile name sent is used to determine the scoreboard team which name we rewrite in other packets, also adds missing component rewriter calls to the display names (Not that important given its only translation keys, but we are already here).

Co-authored-by: dewgs <23721849+dewgs@users.noreply.github.com>
2025-06-25 13:31:17 +02:00
FlorianMichael 6716beec5a Remove arbitrary chat-nbt-fix config option in 1.11.1->1.12 (#4551) 2025-06-25 13:28:23 +02:00
Nassim Jahnke d22b00e4a6 Add helper methods for registry entry rewriting 2025-06-22 22:53:08 +02:00
Nassim Jahnke fe9ca49920 Update mcstructs 2025-06-22 10:38:33 +02:00
PacksoliteandNassim Jahnke e1837dc578 Fix legacy block picking on some Paper forks (#4496)
Co-authored-by: Nassim Jahnke <nassim@njahnke.dev>
2025-06-21 11:22:22 +02:00
booky 66eead2927 Fix missing clouds in 1.21.5->1.21.6 (#4538) 2025-06-21 11:00:19 +02:00
booky 937a2a2532 Fix server links button not visible in 1.21.5->1.21.6 (#4536)
The Minecraft 1.21.6 client will only show the server links if the the server_links dialog has been sent
2025-06-21 01:47:34 +02:00
Nassim Jahnke bee45ef9ef Use Cache get instead of Map compute
This may or may not fix concurrency issues from... somewhere (bad plugins/old guava impl?)
2025-06-20 21:40:37 +02:00
FlorianMichael 1946a65ab2 Add MathUtil#ceil 2025-06-20 21:36:44 +02:00
Nassim Jahnke f594a946d4 Bump version to 5.4.1-SNAPSHOT 2025-06-20 21:36:33 +02:00
Nassim Jahnke 7a0ec492d1 5.4.0 Release 2025-06-20 19:26:25 +02:00
Nassim Jahnke b4fac61eb9 Fix tinted leaves particle reading in 1.21.6 type 2025-06-20 19:26:19 +02:00
Nassim Jahnke 7817b7a422 Remove snapshot version 2025-06-17 02:14:13 +02:00
Nassim Jahnke ed266d296e 1.21.6-rc1 2025-06-17 02:13:06 +02:00
Nassim Jahnke 3ce324c1e1 1.21.6-pre4 2025-06-17 02:13:06 +02:00
Nassim Jahnke 835dc4733d 1.21.6-pre3 2025-06-17 02:13:06 +02:00
Nassim Jahnke aa66a6b482 1.21.6-pre2 2025-06-17 02:13:05 +02:00
Nassim Jahnke 406855d427 1.21.6-pre1 2025-06-17 02:13:05 +02:00
Nassim Jahnke fe5ba84f7a 25w21a 2025-06-17 02:13:05 +02:00
Nassim Jahnke f49495162b Use updated versioned types 2025-06-17 02:13:05 +02:00
Nassim Jahnke be5c451f42 25w20a 2025-06-17 02:13:05 +02:00
Nassim Jahnke 1517596a9f Add hashed item handling 2025-06-17 02:13:05 +02:00
Nassim Jahnke 6a89b84879 Fix attribute modifier writing 2025-06-17 02:13:05 +02:00
Nassim Jahnke c414458f1c 25w19a 2025-06-17 02:13:05 +02:00
Nassim Jahnke ec9086abc4 25w18a 2025-06-17 02:13:05 +02:00
Nassim Jahnke d6c16677fc 25w17a 2025-06-17 02:13:05 +02:00
Nassim Jahnke 7cd3a75ef8 Handle player_command change 2025-06-17 02:13:05 +02:00
Nassim Jahnke 0677cbaa3c 25w16a 2025-06-17 02:13:05 +02:00
Nassim Jahnke ab8b5abc48 25w15a
Is it 1.22? Is it 1.21.6? Who knows
2025-06-17 02:13:05 +02:00
FlorianMichael 60c67659d0 Filter invalid characters in command click events in 1.21.4->.5 (#4528)
Minecraft versions prior to 1.21.4 filter out invalid characters when handling the click event on the clientside while 1.21.5+ validates and throws in the network codec per ExtraCodecs#CHAT_STRING
2025-06-15 12:28:08 +02:00
dewgsandFlorianMichael 814190c2df Add missing dimension change checks for entity tracking (#4527)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-06-14 17:29:40 +02:00
RK_01 04d647bfef Fix respawning with 1.21.2+ clients on older vanilla servers (#4509) 2025-06-12 18:18:37 +02:00
FlorianMichael 930bf67229 Don't always send player inputs on Fabric servers in 1.21->1.21.2 (#4523) 2025-06-11 02:52:21 +02:00
FlorianMichael 51c3085180 Validate tag identifiers in block predicates in 1.20.3->1.20.5 (#4522)
As usual, versions <= 1.20.4 have the entire parsing code in a try catch block while 1.20.5+ needs valid data.

Closes https://github.com/ViaVersion/ViaVersion/issues/4515
2025-06-09 15:08:00 +02:00
FlorianMichael b981223e0a Make workflows manual runnable (#4521) 2025-06-08 23:56:14 +02:00
FlorianMichael 3951cff03a Cancel out unmapped (block) ids in HolderSetImpl (#4512)
In VB, mapping data will return -1 for missing block ids (which is for almost all blocks the case). This is made so that VV rewriters can cancel these blocks away nicely (as mostly used in places where it's better to show the user nothing rather than wrong blocks, such as statistics).

Fixes https://github.com/ViaVersion/ViaVersion/issues/4510
2025-05-28 07:41:21 +02:00
Nassim Jahnke 77a6ae37c0 Fix game profile null id hashing
Fixes #4506
2025-05-27 15:28:35 +02:00
Nassim Jahnke 12e201633f Fix rabbit variant hashing 2025-05-27 14:28:04 +02:00
Nassim Jahnke 8eb005e775 Fix tropical fish pattern hashing 2025-05-27 14:05:40 +02:00
RK_01 4d39c0007f Add QoL API for GameProfile (#4505) 2025-05-27 08:39:08 +02:00
FlorianMichael d9609e60b8 Don't fail on book pages rewrite in 1.8->1.9 as per Vanilla behaviour (#4504) 2025-05-26 20:22:29 +02:00
Nassim Jahnke ab3927dff7 Implement our own hash writing
This avoids a lot of indirection, wrapping/boxing and data copying while also making sure we can immediately implement them on new snapshots without waiting for a separate (also ever-growing) library.

The HashBuilder is partially copied from MCStructs, everything else was built anew to intentionally stay away from Vanilla's Codec design
2025-05-26 12:37:58 +02:00
FlorianMichael 1a60c52fa3 Don't convert creative-slot-lock/map-post-processing in 1.20.3->.5 (#4500) 2025-05-22 21:38:18 +02:00
github-actions[bot]andgradle-update-robot f88dae1828 Update Gradle Wrapper from 8.14 to 8.14.1 (#4501)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-05-22 17:35:05 +02:00
Nassim JahnkeandFlorianMichael 2626773267 Refactor 1.20.5+ versioned types
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-05-17 15:12:52 +02:00
Nassim Jahnke f16f1905b7 Move container handling into handleShowItem directly
Fixes ViaVersion/ViaBackwards#1010
2025-05-15 11:08:44 +02:00
Nassim Jahnke cc435b2b02 Move item id setter below backup method 2025-05-14 14:01:03 +02:00
Nassim Jahnke eb2d603aae Add protected handleRewritablesToServer method 2025-05-14 13:29:40 +02:00
Nassim Jahnke c30e0f45bc Split up item rewriter methods even more
Item backups and its restoration processes have to be more carefully placed around Rewritable handling, so the original/restored data stays untouched
2025-05-14 13:22:32 +02:00
Nassim Jahnke ebb24c73a2 Don't call super handleItemToClient with custom item hasher 2025-05-13 23:12:06 +02:00
Nassim Jahnke 575c5b9abf Move restoreBackupData call up 2025-05-13 22:55:46 +02:00
Nassim Jahnke 812694d74d Split updateItemDataComponents in two 2025-05-13 22:45:25 +02:00
Nassim Jahnke 1efaffbc7d Implement more data conversion
Most importantly attributes
2025-05-12 18:59:41 +02:00
FlorianMichael b03b5f7da7 [ci skip] Make the runViaProxy task work with Gradle's configuration cache (#4483) 2025-05-12 17:53:54 +02:00
Nassim Jahnke 3554db9e3a Prepare for hashed item rewriting 2025-05-11 23:10:20 +02:00
Nassim Jahnke a6d58fc02b Only track item when necessary, cleanup 2025-05-11 23:10:18 +02:00
RaphiMC e2045295a0 Hash item data components in 1.21.4->1.21.5 2025-05-11 23:10:17 +02:00
FlorianMichael a6b219c0df [ci skip] Allow build if Git is not installed or the project is downloaded as code zip (#4477) 2025-05-11 22:26:35 +02:00
FlorianMichael 0b5721d81e Check for non-negative value for damage & repair cost in 1.20.3->.5 (#4491)
In 1.20.5, codecs introduced the non-negative int type which will fail if a value <= 0 is present. In 1.20.4, Mojang gracefully handled negative values

Fixes https://github.com/ViaVersion/ViaFabricPlus/issues/763
2025-05-11 22:05:59 +02:00
FlorianMichael 5bad61e210 Don't perform length validation on zero bit storage in 1.18 palette type (#4479)
Minecraft has its own ZeroBitStorage type for this case so we don't need to perform the validation, also removed the comments as this is just how our code should work to match Vanilla behaviour (at least for the first one; I did not verify the readValues code)

Closes https://github.com/ViaVersion/ViaVersion/issues/4476
2025-05-05 21:06:37 +02:00
FlorianMichael e597d8faaa [ci skip] Include platform launcher runtime dependency for tests (#4474) 2025-04-29 10:21:30 +02:00
FelixandFlorianMichael d9eb7109bd Add missing PLAYER_CHAT handlers in 1.20/1.21 versions (#4472)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-04-28 11:57:10 +02:00
github-actions[bot]andgradle-update-robot 77d68306b6 Update Gradle Wrapper from 8.13 to 8.14 (#4471)
Signed-off-by: gradle-update-robot <gradle-update-robot@regolo.cc>
Co-authored-by: gradle-update-robot <gradle-update-robot@regolo.cc>
2025-04-26 16:33:53 +02:00
FlorianMichael 16aec9c0a1 Fix legacy item/entity hover event + potion id in 1.21.4->1.21.5 (#4469) 2025-04-23 20:52:53 +02:00
FlorianMichael c6cde5fc10 Cancel unknown block entities in BlockRewriter#registerBlockEntityData (#4466) 2025-04-22 16:05:44 +02:00
Nassim Jahnke bf84eb0141 Add separate config option for text component conversion errors 2025-04-20 15:57:22 +02:00
Nassim Jahnke 4dfc3bd2be Make parts of item data component rewriting more generic via an interface 2025-04-16 10:59:20 +02:00
Nassim Jahnke b0c53ffdd3 Make helper method in Copyable static 2025-04-15 21:20:57 +02:00
Nassim Jahnke d65b2abc46 Ignore invalid data in signs 2025-04-15 20:46:13 +02:00
Nassim Jahnke 03313a1681 Catch text conversion errors 2025-04-15 10:02:00 +02:00
Nassim Jahnke 78c5e2c8e3 Convert hover events to legacy deep 2025-04-14 08:57:04 +02:00
FlorianMichael e467c7c03f Set correct data types in 1.8->1.9 CONTAINER_CLICK (#4460) 2025-04-14 08:55:45 +02:00
Nassim Jahnke 0c01425641 5.3.2 Release 2025-04-13 15:45:15 +02:00
Nassim Jahnke 01d26e7ac5 Make trimStrings public 2025-04-12 15:37:19 +02:00
Nassim Jahnke 99ea6c32ad Add client and server protocol to informative exception data 2025-04-11 22:20:38 +02:00
Nassim Jahnke cf231d92b1 Update mcstructs
Fixes ViaVersion/ViaBackwards#988
2025-04-10 18:58:23 +02:00
FlorianMichael f555188428 [ci skip] Print correct max read length in StringType sanity checks (#4456) 2025-04-10 16:16:46 +02:00
FlorianMichael 93d6fa2e78 Only add (block) entity id if needed for tooltips in 1.20.3->.5 2025-04-09 17:22:33 +02:00
Nassim Jahnke 162fcafb36 Ignore unknown entity data too in 1.20.3->1.20.5
Fixes #4433
Closes #4451
2025-04-09 16:24:03 +02:00
FlorianMichael 3d0a0fe590 Send player input every tick when in boat in 1.21->1.21.2 (#4449) 2025-04-09 16:14:07 +02:00
bookyandFlorianMichael b06556a84e Fix advancement menu background keys (#4454)
Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
2025-04-09 15:56:06 +02:00
Nassim Jahnke ac8bb104b3 Fix primitive array copying 2025-04-08 15:54:02 +02:00
FlorianMichael 4b85ca7691 Fix handling of removed item components in 1.20.3->.5 component rewriter (#4452)
Only relevant for VB though as VV will never put empty structured data through it.
2025-04-08 15:34:30 +02:00
FlorianMichael ebd8eb79c1 Use correct version in json to tag conversion in 1.21.4->.5 (#4450) 2025-04-08 15:32:07 +02:00
Nassim Jahnke 09cffbfb33 Null check connection in Velocity connect listener 2025-04-05 18:35:24 +02:00
FlorianMichael 49a1bffc98 Only send the connection details if ViaVersion is active (#4434) 2025-04-05 11:54:06 +02:00
FlorianMichael da022a0b63 [ci skip] Fix ItemRewriter#registerContainerClick1_21_5 data order (#4435) 2025-04-05 11:53:36 +02:00
Nassim Jahnke 3beddaf522 Move show item container contents conversion to the right place
Fixes #4444
2025-04-05 11:53:08 +02:00
Nassim Jahnke 70139c6838 Bump version to 5.3.2-SNAPSHOT 2025-04-05 11:52:24 +02:00
281 changed files with 7601 additions and 1607 deletions

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
name: Java CI with Gradle
on: [push, pull_request]
on: [push, pull_request, workflow_dispatch]
jobs:
build:
+1
View File
@@ -4,6 +4,7 @@ on:
branches:
- master
- dev
workflow_dispatch:
jobs:
publish:
+10
View File
@@ -0,0 +1,10 @@
# Security Policy
## Reporting a Vulnerability
If you discover a **security vulnerability**, please **do not** open a public issue. Instead, use one of the following **confidential contact methods**:
* **Email:** [security@viaversion.com](mailto:security@viaversion.com)
* **Discord:** Join our [Discord server](https://discord.gg/viaversion) and visit the [#exploit-report](https://discord.com/channels/316206679014244363/1388847764137316485) channel for further instructions.
If your issue is **not security-related** (e.g., bug reports, feature requests, or usage questions), please use the [GitHub Issues page](https://github.com/ViaVersion/ViaVersion/issues) or contact us via the [Discord server](https://discord.gg/viaversion).
+5 -2
View File
@@ -24,13 +24,16 @@ dependencies {
}
implementation(rootProject.libs.text) {
exclude("com.google.code.gson", "gson")
exclude("com.google.guava", "guava")
exclude("com.viaversion", "nbt")
}
api(libs.snakeYaml)
compileOnlyApi(libs.netty)
compileOnlyApi(libs.guava)
compileOnlyApi(libs.guava) {
exclude("com.google.errorprone", "error_prone_annotations")
exclude("org.jspecify", "jspecify")
exclude("com.google.j2objc", "j2objc-annotations")
}
compileOnlyApi(libs.checkerQual)
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2024 ViaVersion and contributors
* 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
@@ -233,13 +233,6 @@ public interface ViaVersionConfig extends Config {
*/
boolean isChunkBorderFix();
/**
* Should we fix nbt array's in json chat messages for 1.12 clients
*
* @return true if enabled
*/
boolean is1_12NBTArrayFix();
/**
* Should we make team colours based on the last colour in team prefix
*
@@ -285,6 +278,13 @@ public interface ViaVersionConfig extends Config {
*/
boolean isSuppressConversionWarnings();
/**
* Should we hide errors that occur when trying to convert text components?
*
* @return true if enabled
*/
boolean isSuppressTextComponentConversionWarnings();
/**
* Should we disable the 1.13 auto-complete feature to stop spam kicks? (for any server lower than 1.13)
*
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.connection;
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
@@ -99,6 +100,23 @@ public interface UserConnection {
*/
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
/**
* Adds an item hasher to the user connection.
*
* @param protocolClass protocol class
* @param itemHasher item hasher
*/
void addItemHasher(Class<? extends Protocol> protocolClass, ItemHasher itemHasher);
/**
* Returns the item hasher by the given protocol class if present.
*
* @param protocolClass protocol class
* @param <T> item hasher type
* @return item hasher if present
*/
@Nullable <T extends ItemHasher> T getItemHasher(Class<? extends Protocol> protocolClass);
/**
* Returns the client world by the given protocol class if present.
*
@@ -208,8 +208,8 @@ public class MappingDataBase implements MappingData {
}
@Override
public int getOldSoundId(final int i) {
return soundMappings.getNewIdOrDefault(i, 0);
public int getOldSoundId(final int id) {
return soundMappings.inverse().getNewIdOrDefault(id, 0);
}
@Override
@@ -0,0 +1,51 @@
/*
* 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.data.item;
import java.util.List;
/**
* Used for converting items to hashed items and caching them for later use during serverbound packets.
* <p>
* Most of this stays in the internal module given non-permanent, imperfect caching as well as missing converters.
*/
public interface ItemHasher {
/**
* Returns whether this connection is currently processing a clientbound player inventory packet.
* <p>
* Used for checking when it is necessary to track/process item data hashes.
*
* @return true if processing a clientbound inventory packet, false otherwise
*/
boolean isProcessingClientboundInventoryPacket();
void setProcessingClientboundInventoryPacket(boolean processingClientboundInventoryPacket);
/**
* Sets the enchantment registry for this connection.
*
* @param enchantments list of enchantment identifiers
*/
void setEnchantments(List<String> enchantments);
}
@@ -58,7 +58,7 @@ public class BlockChangeRecord1_16_2 implements BlockChangeRecord {
@Override
public short getY(int chunkSectionY) {
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: " + chunkSectionY);
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: %s", chunkSectionY);
return (short) ((chunkSectionY << 4) + sectionY);
}
@@ -22,11 +22,31 @@
*/
package com.viaversion.viaversion.api.minecraft;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
public record GameProfile(@Nullable String name, @Nullable UUID id, Property[] properties) {
public GameProfile(@Nullable final String name, @Nullable final UUID id) {
this(name, id, new Property[0]);
}
public Map<String, List<Property>> propertiesMap() {
final Map<String, List<Property>> map = new HashMap<>();
for (Property property : properties) {
map.computeIfAbsent(property.name(), k -> new ArrayList<>()).add(property);
}
return map;
}
public record Property(String name, String value, @Nullable String signature) {
public Property(final String name, final String value) {
this(name, value, null);
}
}
}
@@ -23,6 +23,8 @@
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
import java.util.function.Supplier;
public interface Holder<T> {
@@ -88,5 +90,24 @@ public interface Holder<T> {
* @param rewriteFunction the function to rewrite the id
* @return a new holder with the id rewritten, or self
*/
Holder<T> updateId(final Int2IntFunction rewriteFunction);
default Holder<T> updateId(final Int2IntFunction rewriteFunction) {
return this.updateId(rewriteFunction, null);
}
/**
* Returns a new holder with the id rewritten using the given function, or self if this is a direct holder or the id did not change.
*
* @param rewriteFunction the function to rewrite the id
* @param ifMissing a supplier that provides a new holder if the id is missing (i.e. -1)
* @return a new holder with the id rewritten, or self
*/
Holder<T> updateId(Int2IntFunction rewriteFunction, Supplier<Holder<T>> ifMissing);
/**
* Returns a new holder with the value rewritten using the given function, or self if this is an id holder or the value did not change.
*
* @param rewriteFunction the function to rewrite the value
* @return a new holder with the value rewritten, or self
*/
Holder<T> updateValue(final Function<T, T> rewriteFunction);
}
@@ -67,11 +67,17 @@ final class HolderSetImpl {
@Override
public HolderSet rewrite(final Int2IntFunction idRewriter) {
// Filter out negative ids as they would come from missing VB mapping data. This happens especially
// with block ids which are not mapped and thus written as -1 so VV rewriters can cancel them nicely.
final int[] mappedIds = new int[ids.length];
for (int i = 0; i < mappedIds.length; i++) {
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
int validCount = 0;
for (final int id : ids) {
final int mappedId = idRewriter.applyAsInt(id);
if (mappedId != -1) {
mappedIds[validCount++] = mappedId;
}
}
return new Ids(mappedIds);
return new Ids(validCount == ids.length ? mappedIds : Arrays.copyOf(mappedIds, validCount));
}
@Override
@@ -24,6 +24,8 @@ package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
import java.util.function.Supplier;
record IdHolder<T>(int id) implements Holder<T> {
@@ -47,14 +49,22 @@ record IdHolder<T>(int id) implements Holder<T> {
}
@Override
public Holder<T> updateId(final Int2IntFunction rewriteFunction) {
public Holder<T> updateId(final Int2IntFunction rewriteFunction, final Supplier<Holder<T>> ifMissing) {
final int rewrittenId = rewriteFunction.applyAsInt(id);
if (rewrittenId == id) {
return this;
}
if (rewrittenId == -1) {
if (ifMissing != null) {
return ifMissing.get();
}
throw new IllegalArgumentException("Received invalid id in updateId");
}
return Holder.of(rewrittenId);
}
@Override
public Holder<T> updateValue(final Function<T, T> rewriteFunction) {
return this;
}
}
@@ -121,7 +121,7 @@ public final class Particle implements IdHolder, Copyable {
@Override
public ParticleData<T> copy() {
return new ParticleData<>(type, copy(value));
return new ParticleData<>(type, Copyable.copy(value));
}
@Override
@@ -22,11 +22,21 @@
*/
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record SoundEvent(String identifier, @Nullable Float fixedRange) {
private static final Holder<SoundEvent> UNKNOWN = Holder.of(new SoundEvent("viaversion:unknown", 0F));
public SoundEvent withIdentifier(final String identifier) {
return new SoundEvent(identifier, this.fixedRange);
}
public static @Nullable Holder<SoundEvent> rewriteHolder(@Nullable final Holder<SoundEvent> holder, final Int2IntFunction soundRewriteFunction) {
if (holder == null) {
return null;
}
return holder.updateId(soundRewriteFunction, () -> UNKNOWN);
}
}
@@ -23,6 +23,8 @@
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
import java.util.function.Supplier;
record ValueHolder<T>(T value) implements Holder<T> {
@@ -42,7 +44,13 @@ record ValueHolder<T>(T value) implements Holder<T> {
}
@Override
public Holder<T> updateId(final Int2IntFunction rewriteFunction) {
public Holder<T> updateId(final Int2IntFunction rewriteFunction, final Supplier<Holder<T>> ifMissing) {
return this;
}
@Override
public Holder<T> updateValue(final Function<T, T> rewriteFunction) {
final T rewrittenValue = rewriteFunction.apply(value);
return rewrittenValue != value ? Holder.of(rewrittenValue) : this;
}
}
@@ -0,0 +1,54 @@
/*
* 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.codec;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.util.Key;
import java.util.List;
public interface CodecContext {
RegistryAccess registryAccess();
boolean mapped();
boolean isSupported(StructuredDataKey<?> key);
interface RegistryAccess {
Key item(int id);
Key enchantment(int id);
Key attributeModifier(int id);
Key dataComponentType(int id);
static RegistryAccess of(final List<String> enchantments, final MappingData mappingData) {
return new RegistryAccessImpl(enchantments, mappingData);
}
RegistryAccess withMapped(boolean mapped);
}
}
@@ -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.codec;
import com.viaversion.viaversion.api.type.Type;
import java.util.function.Consumer;
public class DelegatingOps implements Ops {
private final Ops delegate;
public DelegatingOps(final Ops delegate) {
this.delegate = delegate;
}
@Override
public CodecContext context() {
return delegate.context();
}
@Override
public void writeByte(final byte b) {
delegate.writeByte(b);
}
@Override
public void writeBytes(final byte[] array) {
delegate.writeBytes(array);
}
@Override
public void writeBoolean(final boolean b) {
delegate.writeBoolean(b);
}
@Override
public void writeShort(final short s) {
delegate.writeShort(s);
}
@Override
public void writeString(final CharSequence sequence) {
delegate.writeString(sequence);
}
@Override
public void writeInt(final int i) {
delegate.writeInt(i);
}
@Override
public void writeLong(final long l) {
delegate.writeLong(l);
}
@Override
public void writeFloat(final float f) {
delegate.writeFloat(f);
}
@Override
public void writeDouble(final double d) {
delegate.writeDouble(d);
}
@Override
public void writeInts(final int[] array) {
delegate.writeInts(array);
}
@Override
public void writeLongs(final long[] array) {
delegate.writeLongs(array);
}
@Override
public void writeList(final Consumer<ListSerializer> consumer) {
delegate.writeList(consumer);
}
@Override
public void writeMap(final Consumer<MapSerializer> consumer) {
delegate.writeMap(consumer);
}
@Override
public <V> void write(final Type<V> type, final V value) {
delegate.write(type, value);
}
}
@@ -0,0 +1,135 @@
/*
* 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.codec;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import java.util.Objects;
import java.util.function.Consumer;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface Ops {
CodecContext context();
void writeByte(byte b);
void writeBytes(byte[] array);
void writeBoolean(boolean b);
void writeShort(short s);
void writeString(CharSequence sequence);
void writeInt(int i);
void writeLong(long l);
void writeFloat(float f);
void writeDouble(double d);
void writeInts(int[] array);
void writeLongs(long[] array);
void writeList(Consumer<ListSerializer> consumer);
void writeMap(Consumer<MapSerializer> consumer);
<V> void write(final Type<V> type, final V value);
interface ListSerializer {
<V> ListSerializer write(Type<V> valueType, V value);
ListSerializer writeList(Consumer<ListSerializer> consumer);
ListSerializer writeMap(Consumer<MapSerializer> consumer);
}
interface MapSerializer {
<K, V> MapSerializer write(Type<K> keyType, K key, Type<V> valueType, V value);
default <V> MapSerializer write(final String key, final Type<V> type, final V value) {
write(Types.STRING, key, type, value);
return this;
}
/**
* Writes the given value or default value if the value is null.
*
* @param key map key
* @param type type of the value
* @param value the value to write, or null
* @param def default value to write if the value is null
* @return self
* @param <V> value type
*/
default <V> MapSerializer write(final String key, final Type<V> type, @Nullable final V value, final V def) {
write(Types.STRING, key, type, value != null ? value : def);
return this;
}
/**
* Writes the given value if it is not null.
*
* @param key map key
* @param type type of the value
* @param value the value to write, or null
* @return self
* @param <V> value type
*/
default <V> MapSerializer writeOptional(final String key, final Type<V> type, @Nullable final V value) {
if (value != null) {
write(Types.STRING, key, type, value);
}
return this;
}
/**
* Writes the given value if it is not null and not equal to the default value.
*
* @param key map key
* @param type type of the value
* @param value the value to write, or null
* @param def default value to compare against
* @return self
* @param <V> value type
*/
default <V> MapSerializer writeOptional(final String key, final Type<V> type, @Nullable final V value, final V def) {
if (value != null && !Objects.deepEquals(value, def)) {
write(Types.STRING, key, type, value);
}
return this;
}
MapSerializer writeList(String key, Consumer<ListSerializer> consumer);
MapSerializer writeMap(String key, Consumer<MapSerializer> consumer);
<T> MapSerializer writeInlinedMap(Type<T> valueType, T value);
}
}
@@ -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.codec;
import com.viaversion.viaversion.api.data.FullMappings;
import com.viaversion.viaversion.api.data.MappingData;
import com.viaversion.viaversion.util.Key;
import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
final class RegistryAccessImpl implements CodecContext.RegistryAccess {
private final List<String> enchantments;
private final MappingData mappingData;
private final boolean mapped;
RegistryAccessImpl(final List<String> enchantments, final MappingData mappingData) {
this.enchantments = enchantments;
this.mappingData = mappingData;
this.mapped = false;
}
private RegistryAccessImpl(final List<String> enchantments, final MappingData mappingData, final boolean mapped) {
this.enchantments = enchantments;
this.mappingData = mappingData;
this.mapped = mapped;
}
@Override
public Key item(final int id) {
return key(mappingData.getFullItemMappings(), id);
}
@Override
public Key enchantment(final int id) {
final String identifier = id >= 0 && id < this.enchantments.size() ? this.enchantments.get(id) : null;
return key(identifier, id);
}
@Override
public Key attributeModifier(final int id) {
return key(mappingData.getAttributeMappings(), id);
}
@Override
public Key dataComponentType(final int id) {
return key(mappingData.getDataComponentSerializerMappings(), id);
}
private Key key(final FullMappings mappings, final int id) {
final String identifier = mapped ? mappings.mappedIdentifier(id) : mappings.identifier(id);
return key(identifier, id);
}
private Key key(@Nullable final String identifier, final int id) {
return identifier != null ? Key.of(identifier) : Key.of("viaversion", "unknown/" + id);
}
@Override
public CodecContext.RegistryAccess withMapped(final boolean mapped) {
return this.mapped == mapped ? this : new RegistryAccessImpl(this.enchantments, this.mappingData, mapped);
}
}
@@ -0,0 +1,104 @@
/*
* 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.codec;
import com.viaversion.viaversion.api.type.Type;
import java.util.function.Consumer;
public class ThrowingOps implements Ops {
@Override
public CodecContext context() {
throw new UnsupportedOperationException();
}
@Override
public void writeByte(final byte b) {
throw new UnsupportedOperationException();
}
@Override
public void writeBytes(final byte[] array) {
throw new UnsupportedOperationException();
}
@Override
public void writeBoolean(final boolean b) {
throw new UnsupportedOperationException();
}
@Override
public void writeShort(final short s) {
throw new UnsupportedOperationException();
}
@Override
public void writeString(final CharSequence sequence) {
throw new UnsupportedOperationException();
}
@Override
public void writeInt(final int i) {
throw new UnsupportedOperationException();
}
@Override
public void writeLong(final long l) {
throw new UnsupportedOperationException();
}
@Override
public void writeFloat(final float f) {
throw new UnsupportedOperationException();
}
@Override
public void writeDouble(final double d) {
throw new UnsupportedOperationException();
}
@Override
public void writeInts(final int[] array) {
throw new UnsupportedOperationException();
}
@Override
public void writeLongs(final long[] array) {
throw new UnsupportedOperationException();
}
@Override
public void writeList(final Consumer<ListSerializer> consumer) {
throw new UnsupportedOperationException();
}
@Override
public void writeMap(final Consumer<MapSerializer> consumer) {
throw new UnsupportedOperationException();
}
@Override
public <V> void write(final Type<V> type, final V value) {
throw new UnsupportedOperationException();
}
}
@@ -20,22 +20,26 @@
* 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;
package com.viaversion.viaversion.api.minecraft.codec.hash;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType1_12;
import java.util.List;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
public final class Types1_12 {
/**
* Hash operations. Note that this is different from Vanilla codecs, where this
* instead acts as a (re-usable) hasher directly rather than each method having
* self-contained return values.
*/
public interface Hasher extends Ops {
/**
* Entity data type for 1.12
* Returns the current hash value.
*
* @return the current hash value
*/
public static final Type<EntityData> ENTITY_DATA = new EntityDataType1_12();
int hash();
/**
* Entity data list type for 1.12
* Resets the hasher to its initial state.
*/
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
void reset();
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft.data;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import java.util.Objects;
@@ -61,7 +62,7 @@ final class FilledStructuredData<T> implements StructuredData<T> {
@Override
public StructuredData<T> copy() {
return new FilledStructuredData<>(this.key, this.copy(this.value), this.id);
return new FilledStructuredData<>(this.key, Copyable.copy(this.value), this.id);
}
@Override
@@ -241,7 +241,7 @@ public final class StructuredDataContainer implements Copyable {
/**
* Sets the lookup for serializer ids. Required to call most of the other methods.
*
* @param protocol protocol to retreive the id of the serializer from
* @param protocol protocol to retrieve the id of the serializer from
* @param mappedNames if the names are mapped (true if structures from the mapped version are added, false for the unmapped version)
*/
public void setIdLookup(final Protocol<?, ?, ?, ?> protocol, final boolean mappedNames) {
@@ -284,6 +284,10 @@ public final class StructuredDataContainer implements Copyable {
return data;
}
public boolean isEmpty() {
return data.isEmpty();
}
@Override
public String toString() {
return "StructuredDataContainer{" +
@@ -30,9 +30,10 @@ 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.data.version.StructuredDataKeys1_20_5;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_2;
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_5;
import com.viaversion.viaversion.api.minecraft.item.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;
@@ -45,9 +46,10 @@ import com.viaversion.viaversion.api.minecraft.item.data.CustomModelData1_21_4;
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant;
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantable;
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
import com.viaversion.viaversion.api.minecraft.item.data.EnumTypes;
import com.viaversion.viaversion.api.minecraft.item.data.Equippable;
import com.viaversion.viaversion.api.minecraft.item.data.FilterableString;
import com.viaversion.viaversion.api.minecraft.item.data.FireworkExplosion;
import com.viaversion.viaversion.api.minecraft.item.data.Fireworks;
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_20_5;
@@ -62,22 +64,29 @@ 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.TropicalFishPattern;
import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable;
import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
import com.viaversion.viaversion.api.minecraft.item.data.Weapon;
import com.viaversion.viaversion.api.minecraft.item.data.WritableBook;
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.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.util.Either;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Unit;
/**
* Holds data component keys.
*
* @param identifier string identifier
* @param type data type
* @param <T> data type
* @see VersionedTypes
*/
public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<CompoundTag> CUSTOM_DATA = new StructuredDataKey<>("custom_data", Types.COMPOUND_TAG);
@@ -86,20 +95,20 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> DAMAGE = new StructuredDataKey<>("damage", Types.VAR_INT);
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<Tag> CUSTOM_NAME = new StructuredDataKey<>("custom_name", Types.TEXT_COMPONENT_TAG);
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TEXT_COMPONENT_TAG);
public static final StructuredDataKey<Key> ITEM_MODEL = new StructuredDataKey<>("item_model", Types.RESOURCE_LOCATION);
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", new ArrayType<>(Types.TEXT_COMPONENT_TAG, 256));
public static final StructuredDataKey<Integer> RARITY = new StructuredDataKey<>("rarity", EnumTypes.RARITY);
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);
// 1.21.5+ predicates are in their own key classes
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.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<AttributeModifiers1_21> ATTRIBUTE_MODIFIERS1_21_6 = new StructuredDataKey<>("attribute_modifiers", AttributeModifiers1_21.TYPE1_21_6);
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);
@@ -113,21 +122,19 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_21);
public static final StructuredDataKey<FoodProperties1_21_2> FOOD1_21_2 = new StructuredDataKey<>("food", FoodProperties1_21_2.TYPE);
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
public static final StructuredDataKey<Item> USE_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> 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<Enchantable> ENCHANTABLE = new StructuredDataKey<>("enchantable", Enchantable.TYPE);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_2 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_2);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_5 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_5);
public static final StructuredDataKey<Equippable> EQUIPPABLE1_21_6 = new StructuredDataKey<>("equippable", Equippable.TYPE1_21_6);
public static final StructuredDataKey<HolderSet> REPAIRABLE = new StructuredDataKey<>("repairable", Types.HOLDER_SET);
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
public static final StructuredDataKey<String> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.STRING);
public static final StructuredDataKey<Key> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.RESOURCE_LOCATION);
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
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);
@@ -138,21 +145,11 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> MAP_ID = new StructuredDataKey<>("map_id", Types.VAR_INT);
public static final StructuredDataKey<CompoundTag> MAP_DECORATIONS = new StructuredDataKey<>("map_decorations", Types.COMPOUND_TAG);
public static final StructuredDataKey<Integer> MAP_POST_PROCESSING = new StructuredDataKey<>("map_post_processing", Types.VAR_INT);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_20_5 = new StructuredDataKey<>("charged_projectiles", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21 = new StructuredDataKey<>("charged_projectiles", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_2 = new StructuredDataKey<>("charged_projectiles", Types1_21_2.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_4 = new StructuredDataKey<>("charged_projectiles", Types1_21_4.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> 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<WritableBook> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", WritableBook.TYPE);
public static final StructuredDataKey<WrittenBook> WRITTEN_BOOK_CONTENT = new StructuredDataKey<>("written_book_content", WrittenBook.TYPE);
public static final StructuredDataKey<ArmorTrim> TRIM1_20_5 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_20_5);
public static final StructuredDataKey<ArmorTrim> TRIM1_21_2 = new StructuredDataKey<>("trim", ArmorTrim.TYPE1_21_2);
@@ -169,51 +166,54 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21);
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE1_21_5 = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE1_21_5);
public static final StructuredDataKey<String> PROVIDES_BANNER_PATTERNS = new StructuredDataKey<>("provides_banner_patterns", Types.STRING);
public static final StructuredDataKey<Key> PROVIDES_BANNER_PATTERNS = new StructuredDataKey<>("provides_banner_patterns", Types.TAG_KEY);
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);
public static final StructuredDataKey<Fireworks> FIREWORKS = new StructuredDataKey<>("fireworks", Fireworks.TYPE);
public static final StructuredDataKey<GameProfile> PROFILE = new StructuredDataKey<>("profile", Types.GAME_PROFILE);
public static final StructuredDataKey<String> NOTE_BLOCK_SOUND = new StructuredDataKey<>("note_block_sound", Types.STRING);
public static final StructuredDataKey<Key> NOTE_BLOCK_SOUND = new StructuredDataKey<>("note_block_sound", Types.RESOURCE_LOCATION);
public static final StructuredDataKey<BannerPatternLayer[]> BANNER_PATTERNS = new StructuredDataKey<>("banner_patterns", BannerPatternLayer.ARRAY_TYPE);
public static final StructuredDataKey<Integer> BASE_COLOR = new StructuredDataKey<>("base_color", Types.VAR_INT);
public static final StructuredDataKey<Integer> BASE_COLOR = new StructuredDataKey<>("base_color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
public static final StructuredDataKey<Item[]> CONTAINER1_20_5 = new StructuredDataKey<>("container", Types1_20_5.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_21 = new StructuredDataKey<>("container", Types1_21.ITEM_ARRAY);
public static final StructuredDataKey<Item[]> CONTAINER1_21_2 = new StructuredDataKey<>("container", 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> VILLAGER_VARIANT = new StructuredDataKey<>("villager/variant", EnumTypes.VILLAGER_TYPE);
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> WOLF_COLLAR = new StructuredDataKey<>("wolf/collar", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> FOX_VARIANT = new StructuredDataKey<>("fox/variant", EnumTypes.FOX_VARIANT);
public static final StructuredDataKey<Integer> SALMON_SIZE = new StructuredDataKey<>("salmon/size", EnumTypes.SALMON_VARIANT);
public static final StructuredDataKey<Integer> PARROT_VARIANT = new StructuredDataKey<>("parrot/variant", EnumTypes.PARROT_VARIANT);
public static final StructuredDataKey<TropicalFishPattern> TROPICAL_FISH_PATTERN = new StructuredDataKey<>("tropical_fish/pattern", TropicalFishPattern.TYPE);
public static final StructuredDataKey<Integer> TROPICAL_FISH_BASE_COLOR = new StructuredDataKey<>("tropical_fish/base_color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> TROPICAL_FISH_PATTERN_COLOR = new StructuredDataKey<>("tropical_fish/pattern_color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> MOOSHROOM_VARIANT = new StructuredDataKey<>("mooshroom/variant", EnumTypes.MUSHROOM_COW_VARIANT);
public static final StructuredDataKey<Integer> RABBIT_VARIANT = new StructuredDataKey<>("rabbit/variant", EnumTypes.RABBIT_VARIANT);
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<Integer> HORSE_VARIANT = new StructuredDataKey<>("horse/variant", EnumTypes.HORSE_VARIANT);
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> LLAMA_VARIANT = new StructuredDataKey<>("llama/variant", EnumTypes.LLAMA_VARIANT);
public static final StructuredDataKey<Integer> AXOLOTL_VARIANT = new StructuredDataKey<>("axolotl/variant", EnumTypes.AXOLOTL_VARIANT);
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);
public static final StructuredDataKey<Integer> CAT_COLLAR = new StructuredDataKey<>("cat/collar", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> SHEEP_COLOR = new StructuredDataKey<>("sheep/color", EnumTypes.DYE_COLOR);
public static final StructuredDataKey<Integer> SHULKER_COLOR = new StructuredDataKey<>("shulker/color", EnumTypes.DYE_COLOR);
// These are only safe to use after protocol loading
public static final StructuredDataKeys1_20_5 V1_20_5 = VersionedTypes.V1_20_5.structuredDataKeys();
public static final StructuredDataKeys1_20_5 V1_21 = VersionedTypes.V1_21.structuredDataKeys();
public static final StructuredDataKeys1_21_2 V1_21_2 = VersionedTypes.V1_21_2.structuredDataKeys();
public static final StructuredDataKeys1_21_2 V1_21_4 = VersionedTypes.V1_21_4.structuredDataKeys();
public static final StructuredDataKeys1_21_5 V1_21_5 = VersionedTypes.V1_21_5.structuredDataKeys();
public static final StructuredDataKeys1_21_5 V1_21_6 = VersionedTypes.V1_21_6.structuredDataKeys();
@Override
public String toString() {
@@ -0,0 +1,40 @@
/*
* 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.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys1_20_5 extends VersionedStructuredDataKeys {
public final StructuredDataKey<Item[]> container;
public final StructuredDataKey<Item[]> chargedProjectiles;
public final StructuredDataKey<Item[]> bundleContents;
public StructuredDataKeys1_20_5(final VersionedTypesHolder types) {
this.container = add("container", types.itemArray());
this.chargedProjectiles = add("charged_projectiles", types.itemArray());
this.bundleContents = add("bundle_contents", types.itemArray());
}
}
@@ -0,0 +1,43 @@
/*
* 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.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.minecraft.item.data.ContainterContents.ContainerContentsType;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys1_21_2 extends VersionedStructuredDataKeys {
public final StructuredDataKey<Item[]> container;
public final StructuredDataKey<Item[]> chargedProjectiles;
public final StructuredDataKey<Item[]> bundleContents;
public final StructuredDataKey<Item> useRemainder;
public StructuredDataKeys1_21_2(final VersionedTypesHolder types) {
this.container = add("container", new ContainerContentsType(types.item()));
this.chargedProjectiles = add("charged_projectiles", types.itemArray());
this.bundleContents = add("bundle_contents", types.itemArray());
this.useRemainder = add("use_remainder", types.item());
}
}
@@ -0,0 +1,43 @@
/*
* 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.version;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
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.type.types.version.VersionedTypesHolder;
public class StructuredDataKeys1_21_5 extends StructuredDataKeys1_21_2 {
public final StructuredDataKey<AdventureModePredicate> canPlaceOn;
public final StructuredDataKey<AdventureModePredicate> canBreak;
public StructuredDataKeys1_21_5(final VersionedTypesHolder types) {
super(types);
final AdventureModePredicateType1_21_5 adventureModePredicateType = new AdventureModePredicateType1_21_5(types.structuredDataArray());
this.canPlaceOn = add("can_place_on", adventureModePredicateType);
this.canBreak = add("can_break", adventureModePredicateType);
this.unsupportedForOps.add(this.canPlaceOn);
this.unsupportedForOps.add(this.canBreak);
}
}
@@ -20,25 +20,31 @@
* 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;
package com.viaversion.viaversion.api.minecraft.data.version;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.chunk.ChunkSectionType1_9;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType1_9;
import it.unimi.dsi.fastutil.objects.ReferenceArraySet;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public final class Types1_9 {
/**
* Entity data type for 1.9
*/
public static final Type<EntityData> ENTITY_DATA = new EntityDataType1_9();
/**
* Entity data list type for 1.9
*/
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
public abstract class VersionedStructuredDataKeys {
public static final Type<ChunkSection> CHUNK_SECTION = new ChunkSectionType1_9();
private final List<StructuredDataKey<?>> keys = new ArrayList<>();
protected final Set<StructuredDataKey<?>> unsupportedForOps = new ReferenceArraySet<>();
protected <T> StructuredDataKey<T> add(final String identifier, final Type<T> type) {
final StructuredDataKey<T> key = new StructuredDataKey<>(identifier, type);
this.keys.add(key);
return key;
}
public List<StructuredDataKey<?>> keys() {
return this.keys;
}
public boolean supportsOps(final StructuredDataKey<?> key) {
return !unsupportedForOps.contains(key);
}
}
@@ -0,0 +1,318 @@
/*
* 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_6 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),
HAPPY_GHAST(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_6(final EntityType parent) {
this.parent = parent;
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
}
EntityTypes1_21_6(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);
}
}
@@ -22,12 +22,9 @@
*/
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_20_5 extends AbstractEntityDataTypes {
@@ -38,7 +35,7 @@ public final class EntityDataTypes1_20_5 extends AbstractEntityDataTypes {
public final EntityDataType stringType = add(4, Types.STRING);
public final EntityDataType componentType = add(5, Types.TAG);
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
public final EntityDataType itemType = add(7, Types1_20_5.ITEM);
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);
@@ -63,9 +60,10 @@ public final class EntityDataTypes1_20_5 extends AbstractEntityDataTypes {
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
public EntityDataTypes1_20_5(final ParticleType particleType, final ArrayType<Particle> particlesType) {
public EntityDataTypes1_20_5(final VersionedTypesHolder types) {
super(31);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -23,14 +23,10 @@
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
@@ -66,10 +62,10 @@ public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
public EntityDataTypes1_21(final Type<Item> itemType, final ParticleType particleType, final ArrayType<Particle> particlesType) {
public EntityDataTypes1_21(final VersionedTypesHolder types) {
super(31);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -23,13 +23,10 @@
package com.viaversion.viaversion.api.minecraft.entitydata.types;
import com.viaversion.viaversion.api.minecraft.PaintingVariant;
import com.viaversion.viaversion.api.minecraft.Particle;
import com.viaversion.viaversion.api.minecraft.WolfVariant;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
import com.viaversion.viaversion.api.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;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_21_2 extends AbstractEntityDataTypes {
@@ -65,10 +62,10 @@ public final class EntityDataTypes1_21_2 extends AbstractEntityDataTypes {
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
public EntityDataTypes1_21_2(final Type<Item> itemType, final ParticleType particleType, final Type<Particle[]> particlesType) {
public EntityDataTypes1_21_2(final VersionedTypesHolder types) {
super(31);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -23,12 +23,9 @@
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;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
public final class EntityDataTypes1_21_5 extends AbstractEntityDataTypes {
@@ -68,10 +65,10 @@ public final class EntityDataTypes1_21_5 extends AbstractEntityDataTypes {
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) {
public EntityDataTypes1_21_5(final VersionedTypesHolder types) {
super(35);
this.itemType = add(7, itemType);
this.particleType = add(17, particleType);
this.particlesType = add(18, particlesType);
this.itemType = add(7, types.item());
this.particleType = add(17, types.particle());
this.particlesType = add(18, types.particles());
}
}
@@ -39,4 +39,7 @@ public interface HashedItem extends ItemBase {
Int2IntMap dataHashesById();
IntSet removedDataIds();
@Override
HashedItem copy();
}
@@ -79,6 +79,11 @@ public class HashedStructuredItem implements HashedItem {
return this.removedData;
}
@Override
public HashedItem copy() {
return new HashedStructuredItem(identifier, amount, new Int2IntOpenHashMap(dataHashes), new IntOpenHashSet(removedData));
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
@@ -27,7 +27,7 @@ import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
import com.viaversion.viaversion.util.Copyable;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface Item extends ItemBase, Copyable {
public interface Item extends ItemBase {
/**
* Returns the item data. Always 0 for 1.13+ items.
@@ -22,11 +22,13 @@
*/
package com.viaversion.viaversion.api.minecraft.item;
import com.viaversion.viaversion.util.Copyable;
/**
* @see Item
* @see HashedItem
*/
public interface ItemBase {
public interface ItemBase extends Copyable {
/**
* Returns the item identifier.
@@ -64,4 +66,7 @@ public interface ItemBase {
default boolean isEmpty() {
return identifier() == 0 || amount() <= 0;
}
@Override
ItemBase copy();
}
@@ -22,14 +22,17 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record AdventureModePredicate(BlockPredicate[] predicates, boolean showInTooltip) implements Copyable {
public record AdventureModePredicate(BlockPredicate[] predicates,
boolean showInTooltip) implements Copyable, Rewritable {
public AdventureModePredicate(final BlockPredicate[] predicates) {
this(predicates, true);
@@ -70,16 +73,17 @@ public record AdventureModePredicate(BlockPredicate[] predicates, boolean showIn
}
}
public AdventureModePredicate rewrite(final Int2IntFunction blockIdRewriter) {
@Override
public AdventureModePredicate rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final BlockPredicate[] predicates = new BlockPredicate[this.predicates.length];
for (int i = 0; i < predicates.length; i++) {
predicates[i] = this.predicates[i].rewrite(blockIdRewriter);
predicates[i] = this.predicates[i].rewrite(connection, protocol, clientbound);
}
return new AdventureModePredicate(predicates, showInTooltip);
}
@Override
public AdventureModePredicate copy() {
return new AdventureModePredicate(copy(predicates), showInTooltip);
return new AdventureModePredicate(Copyable.copy(predicates), showInTooltip);
}
}
@@ -22,12 +22,15 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern, boolean showInTooltip) {
public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern,
boolean showInTooltip) implements Rewritable {
public ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPattern> pattern) {
this(material, pattern, true);
@@ -96,15 +99,16 @@ public record ArmorTrim(Holder<ArmorTrimMaterial> material, Holder<ArmorTrimPatt
}
};
public ArmorTrim rewrite(final Int2IntFunction idRewriteFunction) {
@Override
public ArmorTrim rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
Holder<ArmorTrimMaterial> material = this.material;
if (material.isDirect()) {
material = Holder.of(material.value().rewrite(idRewriteFunction));
material = Holder.of(material.value().rewrite(connection, protocol, clientbound));
}
Holder<ArmorTrimPattern> pattern = this.pattern;
if (pattern.isDirect()) {
pattern = Holder.of(pattern.value().rewrite(idRewriteFunction));
pattern = Holder.of(pattern.value().rewrite(connection, protocol, clientbound));
}
return new ArmorTrim(material, pattern, showInTooltip);
}
@@ -23,16 +23,19 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
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) implements Copyable {
Map<String, String> overrideArmorMaterials,
Tag description) implements Copyable, Rewritable {
public ArmorTrimMaterial(final String assetName, final int itemId, final Map<String, String> overrideArmorMaterials, final Tag description) {
this(assetName, itemId, 0F, overrideArmorMaterials, description);
@@ -175,8 +178,9 @@ public record ArmorTrimMaterial(String assetName, int itemId, float itemModelInd
}
};
public ArmorTrimMaterial rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimMaterial(assetName, idRewriteFunction.applyAsInt(itemId), itemModelIndex, overrideArmorMaterials, description);
@Override
public ArmorTrimMaterial rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new ArmorTrimMaterial(assetName, Rewritable.rewriteItem(protocol, clientbound, itemId), itemModelIndex, overrideArmorMaterials, description);
}
@Override
@@ -23,13 +23,15 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ArmorTrimPattern(String assetName, int itemId, Tag description, boolean decal) implements Copyable {
public record ArmorTrimPattern(String assetName, int itemId, Tag description, boolean decal) implements Copyable, Rewritable {
public ArmorTrimPattern(final String assetName, final Tag description, final boolean decal) {
this(assetName, 0, description, decal);
@@ -70,8 +72,9 @@ public record ArmorTrimPattern(String assetName, int itemId, Tag description, bo
}
};
public ArmorTrimPattern rewrite(final Int2IntFunction idRewriteFunction) {
return new ArmorTrimPattern(assetName, idRewriteFunction.applyAsInt(itemId), description, decal);
@Override
public ArmorTrimPattern rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return new ArmorTrimPattern(assetName, Rewritable.rewriteItem(protocol, clientbound, itemId), description, decal);
}
@Override
@@ -48,7 +48,7 @@ public record AttributeModifiers1_20_5(AttributeModifier[] modifiers, boolean sh
@Override
public AttributeModifiers1_20_5 copy() {
return new AttributeModifiers1_20_5(copy(modifiers), showInTooltip);
return new AttributeModifiers1_20_5(Copyable.copy(modifiers), showInTooltip);
}
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
@@ -22,10 +22,13 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
@@ -38,27 +41,49 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
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);
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE1_21.read(buffer);
final boolean showInTooltip = buffer.readBoolean();
return new AttributeModifiers1_21(modifiers, showInTooltip);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_21 value) {
AttributeModifier.ARRAY_TYPE.write(buffer, value.modifiers());
AttributeModifier.ARRAY_TYPE1_21.write(buffer, value.modifiers());
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);
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE1_21.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());
AttributeModifier.ARRAY_TYPE1_21.write(buffer, value.modifiers());
}
@Override
public void write(final Ops ops, final AttributeModifiers1_21 value) {
ops.write(AttributeModifier.ARRAY_TYPE1_21, value.modifiers);
}
};
public static final Type<AttributeModifiers1_21> TYPE1_21_6 = new Type<>(AttributeModifiers1_21.class) {
@Override
public AttributeModifiers1_21 read(final ByteBuf buffer) {
final AttributeModifier[] modifiers = AttributeModifier.ARRAY_TYPE1_21_6.read(buffer);
return new AttributeModifiers1_21(modifiers);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifiers1_21 value) {
AttributeModifier.ARRAY_TYPE1_21_6.write(buffer, value.modifiers());
}
@Override
public void write(final Ops ops, final AttributeModifiers1_21 value) {
ops.write(AttributeModifier.ARRAY_TYPE1_21_6, value.modifiers);
}
};
@@ -66,19 +91,25 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
final AttributeModifier[] modifiers = new AttributeModifier[this.modifiers.length];
for (int i = 0; i < this.modifiers.length; i++) {
final AttributeModifier modifier = this.modifiers[i];
modifiers[i] = new AttributeModifier(rewriteFunction.applyAsInt(modifier.attribute()), modifier.modifier(), modifier.slotType());
modifiers[i] = new AttributeModifier(rewriteFunction.applyAsInt(modifier.attribute()), modifier.modifier(), modifier.slotType(), modifier.display());
}
return new AttributeModifiers1_21(modifiers, showInTooltip);
}
@Override
public AttributeModifiers1_21 copy() {
return new AttributeModifiers1_21(copy(modifiers), showInTooltip);
return new AttributeModifiers1_21(Copyable.copy(modifiers), showInTooltip);
}
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
public record AttributeModifier(int attribute, ModifierData modifier, int slotType, Display display) {
private static final String[] EQUIPMENT_SLOT_GROUPS = {"any", "mainhand", "offhand", "hand", "feet", "legs", "chest", "head", "armor", "body", "saddle"};
private static final String[] OPERATION = {"add_value", "add_multiplied_base", "add_multiplied_total"};
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
public AttributeModifier(final int attribute, final ModifierData modifier, final int slotType) {
this(attribute, modifier, slotType, Display.DEFAULT);
}
public static final Type<AttributeModifier> TYPE1_21 = new Type<>(AttributeModifier.class) {
@Override
public AttributeModifier read(final ByteBuf buffer) {
final int attribute = Types.VAR_INT.readPrimitive(buffer);
@@ -93,8 +124,62 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
ModifierData.TYPE.write(buffer, value.modifier);
Types.VAR_INT.writePrimitive(buffer, value.slotType);
}
@Override
public void write(final Ops ops, final AttributeModifier value) {
final Key attribute = ops.context().registryAccess().attributeModifier(value.attribute);
ops.writeMap(map -> map
.write("type", Types.RESOURCE_LOCATION, attribute)
.write("id", Types.RESOURCE_LOCATION, Key.of(value.modifier.id()))
.write("amount", Types.DOUBLE, value.modifier.amount)
.write("operation", Types.STRING, OPERATION[value.modifier.operation()])
.writeOptional("slot", Types.STRING, EQUIPMENT_SLOT_GROUPS[value.slotType()], "any"));
}
};
public static final Type<AttributeModifier[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public static final Type<AttributeModifier[]> ARRAY_TYPE1_21 = new ArrayType<>(TYPE1_21);
public static final Type<AttributeModifier> TYPE1_21_6 = new Type<>(AttributeModifier.class) {
@Override
public AttributeModifier read(final ByteBuf buffer) {
final int attribute = Types.VAR_INT.readPrimitive(buffer);
final ModifierData modifier = ModifierData.TYPE.read(buffer);
final int slot = Types.VAR_INT.readPrimitive(buffer);
final int displayType = Types.VAR_INT.readPrimitive(buffer);
final Display display = displayType == OverrideText.ID ? new OverrideText(Types.TAG.read(buffer)) : new Display(displayType);
return new AttributeModifier(attribute, modifier, slot, display);
}
@Override
public void write(final ByteBuf buffer, final AttributeModifier value) {
Types.VAR_INT.writePrimitive(buffer, value.attribute);
ModifierData.TYPE.write(buffer, value.modifier);
Types.VAR_INT.writePrimitive(buffer, value.slotType);
value.display.write(buffer);
}
@Override
public void write(final Ops ops, final AttributeModifier value) {
final Key attribute = ops.context().registryAccess().attributeModifier(value.attribute);
ops.writeMap(map -> {
map.write("type", Types.RESOURCE_LOCATION, attribute)
.write("id", Types.RESOURCE_LOCATION, Key.of(value.modifier.id()))
.write("amount", Types.DOUBLE, value.modifier.amount)
.write("operation", Types.STRING, OPERATION[value.modifier.operation()])
.writeOptional("slot", Types.STRING, EQUIPMENT_SLOT_GROUPS[value.slotType()], "any");
if (value.display.equals(Display.DEFAULT)) {
return;
}
map.writeMap("display", display -> {
display.write("type", Types.STRING, Display.DISPLAY_TYPES[value.display.id()]);
if (value.display instanceof final OverrideText overrideText) {
display.write("value", Types.TEXT_COMPONENT_TAG, overrideText.component);
}
});
});
}
};
public static final Type<AttributeModifier[]> ARRAY_TYPE1_21_6 = new ArrayType<>(TYPE1_21_6);
}
public record ModifierData(String id, double amount, int operation) {
@@ -116,4 +201,52 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
}
};
}
public static class Display implements Copyable {
public static final String[] DISPLAY_TYPES = {"default", "hidden", "override_text"};
public static final Display DEFAULT = new Display(0);
private final int id;
public Display(final int id) {
this.id = id;
}
public int id() {
return this.id;
}
public void write(final ByteBuf buf) {
Types.VAR_INT.writePrimitive(buf, this.id);
}
@Override
public Display copy() {
return this;
}
}
public static final class OverrideText extends Display {
public static final int ID = 2;
private final Tag component;
public OverrideText(final Tag component) {
super(ID);
this.component = component;
}
public Tag component() {
return this.component;
}
@Override
public void write(final ByteBuf buf) {
super.write(buf);
Types.TAG.write(buf, this.component);
}
@Override
public OverrideText copy() {
return new OverrideText(this.component.copy());
}
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
@@ -46,6 +47,14 @@ public record Bee(CompoundTag entityData, int ticksInHive, int minTicksInHive) i
Types.VAR_INT.writePrimitive(buffer, value.ticksInHive);
Types.VAR_INT.writePrimitive(buffer, value.minTicksInHive);
}
@Override
public void write(final Ops ops, final Bee value) {
ops.writeMap(map -> map
.writeOptional("entity_data", Types.COMPOUND_TAG, value.entityData, new CompoundTag())
.write("ticks_in_hive", Types.INT, value.ticksInHive)
.write("min_ticks_in_hive", Types.INT, value.minTicksInHive));
}
};
public static final Type<Bee[]> ARRAY_TYPE = new ArrayType<>(TYPE);
@@ -23,23 +23,27 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.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.minecraft.data.predicate.DataComponentPredicate;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import 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, DataComponentMatchers dataMatchers) implements Copyable {
@Nullable CompoundTag tag,
DataComponentMatchers dataMatchers) implements Copyable, Rewritable {
public BlockPredicate(@Nullable final HolderSet holderSet, final StatePropertyMatcher @Nullable [] propertyMatchers, @Nullable final CompoundTag tag) {
this(holderSet, propertyMatchers, tag, null);
this(holderSet, propertyMatchers, tag, new DataComponentMatchers(new StructuredData[0], new DataComponentPredicate[0]));
}
public static final Type<BlockPredicate> TYPE1_20_5 = new Type<>(BlockPredicate.class) {
@@ -96,17 +100,18 @@ public record BlockPredicate(@Nullable HolderSet holderSet, StatePropertyMatcher
}
}
public BlockPredicate rewrite(final Int2IntFunction blockIdRewriter) {
@Override
public BlockPredicate rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (holderSet == null || holderSet.hasTagKey()) {
return this;
}
final HolderSet updatedHolders = holderSet.rewrite(blockIdRewriter);
final HolderSet updatedHolders = holderSet.rewrite(Rewritable.blockRewriteFunction(protocol, clientbound));
return new BlockPredicate(updatedHolders, propertyMatchers, tag);
}
@Override
public BlockPredicate copy() {
return new BlockPredicate(holderSet, copy(propertyMatchers), tag == null ? null : tag.copy());
return new BlockPredicate(holderSet, Copyable.copy(propertyMatchers), tag == null ? null : tag.copy());
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
@@ -50,6 +51,15 @@ public record BlockStateProperties(Map<String, String> properties) implements Co
Types.STRING.write(buffer, entry.getValue());
}
}
@Override
public void write(final Ops ops, final BlockStateProperties value) {
ops.writeMap(map -> {
for (final Map.Entry<String, String> entry : value.properties.entrySet()) {
map.write(Types.STRING, entry.getKey(), Types.STRING, entry.getValue());
}
});
}
};
@Override
@@ -22,12 +22,15 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
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.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -39,7 +42,7 @@ public record BlocksAttacks(
@Nullable String bypassedByTag,
@Nullable Holder<SoundEvent> blockSound,
@Nullable Holder<SoundEvent> disableSound
) {
) implements Rewritable {
public static final Type<BlocksAttacks> TYPE = new Type<>(BlocksAttacks.class) {
@@ -67,6 +70,13 @@ public record BlocksAttacks(
}
};
@Override
public BlocksAttacks rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> blockSound = SoundEvent.rewriteHolder(this.blockSound, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> disableSound = SoundEvent.rewriteHolder(this.disableSound, Rewritable.soundRewriteFunction(protocol, clientbound));
return new BlocksAttacks(this.blockDelaySeconds, this.disableCooldownScale, this.damageReductions, this.itemDamage, this.bypassedByTag, blockSound, disableSound);
}
public record DamageReduction(float horizontalBlockingAngle, @Nullable HolderSet type, float base, float factor) {
public static final Type<DamageReduction> TYPE = new Type<>(DamageReduction.class) {
@@ -22,17 +22,20 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
boolean hasConsumeParticles, ConsumeEffect<?>[] consumeEffects) implements Copyable {
boolean hasConsumeParticles,
ConsumeEffect<?>[] consumeEffects) implements Copyable, Rewritable {
public static final Type<?>[] EFFECT_TYPES = {
ApplyStatusEffects.TYPE,
@@ -111,13 +114,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);
@Override
public Consumable1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundHolder = SoundEvent.rewriteHolder(this.sound, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundHolder == this.sound ? this : new Consumable1_21_2(consumeSeconds, animationType, soundHolder, hasConsumeParticles, consumeEffects);
}
@Override
public Consumable1_21_2 copy() {
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, copy(consumeEffects));
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, Copyable.copy(consumeEffects));
}
}
@@ -0,0 +1,55 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-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.codec.Ops;
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.ArrayType;
public final class ContainterContents {
// Just write it as Item[] directly, makes processing easier (until op reading is needed)
public static final class ContainerContentsType extends ArrayType<Item> {
private final Type<Item> itemType;
public ContainerContentsType(final Type<Item> itemType) {
super(itemType, 256);
this.itemType = itemType;
}
@Override
public void write(final Ops ops, final Item[] value) {
ops.writeList(list -> {
for (int i = 0; i < value.length; i++) {
final Item item = value[i];
final int slot = i;
list.writeMap(map -> map
.write("slot", Types.INT, slot)
.write("item", itemType, item));
}
});
}
}
}
@@ -22,12 +22,16 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.ArrayUtil;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[] strings, int[] colors) implements Copyable {
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,10 +50,19 @@ public record CustomModelData1_21_4(float[] floats, boolean[] booleans, String[]
Types.STRING_ARRAY.write(buffer, value.strings());
Types.INT_ARRAY_PRIMITIVE.write(buffer, value.colors());
}
@Override
public void write(final Ops ops, final CustomModelData1_21_4 value) {
ops.writeMap(map -> map
.writeOptional("floats", new ArrayType<>(Types.FLOAT), ArrayUtil.boxedArray(value.floats), new Float[0])
.writeOptional("flags", new ArrayType<>(Types.BOOLEAN), ArrayUtil.boxedArray(value.booleans), new Boolean[0])
.writeOptional("strings", Types.STRING_ARRAY, value.strings(), new String[0])
.writeOptional("colors", new ArrayType<>(Types.INT), ArrayUtil.boxedArray(value.colors), new Integer[0]));
}
};
@Override
public CustomModelData1_21_4 copy() {
return new CustomModelData1_21_4(copy(floats), copy(booleans), copy(strings), copy(colors));
return new CustomModelData1_21_4(Copyable.copy(floats), Copyable.copy(booleans), Copyable.copy(strings), Copyable.copy(colors));
}
}
@@ -22,22 +22,29 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
public record DamageResistant(String typesTagKey) {
public record DamageResistant(Key typesTagKey) {
public static final Type<DamageResistant> TYPE = new Type<>(DamageResistant.class) {
@Override
public DamageResistant read(final ByteBuf buffer) {
final String typesTagKey = Types.STRING.read(buffer);
final Key typesTagKey = Types.RESOURCE_LOCATION.read(buffer);
return new DamageResistant(typesTagKey);
}
@Override
public void write(final ByteBuf buffer, final DamageResistant value) {
Types.STRING.write(buffer, value.typesTagKey());
Types.RESOURCE_LOCATION.write(buffer, value.typesTagKey());
}
@Override
public void write(final Ops ops, final DamageResistant value) {
ops.writeMap(map -> map.write("types", Types.TAG_KEY, value.typesTagKey));
}
};
}
@@ -44,6 +44,6 @@ public record DeathProtection(ConsumeEffect<?>[] deathEffects) implements Copyab
@Override
public DeathProtection copy() {
return new DeathProtection(copy(deathEffects));
return new DeathProtection(Copyable.copy(deathEffects));
}
}
@@ -22,7 +22,9 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public record DyedColor(int rgb, boolean showInTooltip) {
@@ -56,5 +58,10 @@ public record DyedColor(int rgb, boolean showInTooltip) {
public void write(final ByteBuf buffer, final DyedColor value) {
buffer.writeInt(value.rgb);
}
@Override
public void write(final Ops ops, final DyedColor dyedColor) {
ops.write(Types.INT, dyedColor.rgb);
}
};
}
@@ -20,26 +20,29 @@
* 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;
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.chunk.ChunkSectionType1_8;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType1_8;
import java.util.List;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public final class Types1_8 {
public record Enchantable(int value) {
/**
* Entity data type for 1.8
*/
public static final Type<EntityData> ENTITY_DATA = new EntityDataType1_8();
/**
* Entity data list type for 1.8
*/
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
public static final Type<Enchantable> TYPE = new Type<>(Enchantable.class) {
@Override
public Enchantable read(final ByteBuf buffer) {
return new Enchantable(Types.VAR_INT.readPrimitive(buffer));
}
public static final Type<ChunkSection> CHUNK_SECTION = new ChunkSectionType1_8();
@Override
public void write(final ByteBuf buffer, final Enchantable value) {
Types.VAR_INT.writePrimitive(buffer, value.value);
}
@Override
public void write(final Ops ops, final Enchantable enchantable) {
ops.writeMap(map -> map.write("value", Types.INT, enchantable.value));
}
};
}
@@ -22,9 +22,11 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
@@ -81,6 +83,16 @@ public record Enchantments(Int2IntMap enchantments, boolean showInTooltip) imple
Types.VAR_INT.writePrimitive(buffer, entry.getIntValue());
}
}
@Override
public void write(final Ops ops, final Enchantments value) {
ops.writeMap(map -> {
for (final Int2IntMap.Entry entry : value.enchantments.int2IntEntrySet()) {
final Key key = ops.context().registryAccess().enchantment(entry.getIntKey());
map.write(Types.RESOURCE_LOCATION, key, Types.VAR_INT, entry.getIntValue());
}
});
}
};
public Enchantments(final boolean showInTooltip) {
@@ -0,0 +1,53 @@
/*
* 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.types.EnumType;
import com.viaversion.viaversion.api.type.types.EnumType.Fallback;
import com.viaversion.viaversion.api.type.types.FakeEnumType;
import com.viaversion.viaversion.api.type.types.RegistryValueType;
import java.util.List;
import static com.viaversion.viaversion.api.type.types.FakeEnumType.Entry.of;
/**
* Enum types that aren't associated with any specific item data in this package.
*/
public final class EnumTypes {
public static final EnumType DYE_COLOR = new EnumType("white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray", "light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black");
public static final EnumType RARITY = new EnumType("common", "uncommon", "rare", "epic");
public static final EnumType FOX_VARIANT = new EnumType("red", "snow");
public static final EnumType SALMON_VARIANT = new EnumType(Fallback.CLAMP, "small", "medium", "large");
public static final EnumType PARROT_VARIANT = new EnumType(Fallback.CLAMP, "red_blue", "blue", "green", "yellow_blue", "gray");
public static final EnumType MUSHROOM_COW_VARIANT = new EnumType(Fallback.CLAMP, "red", "brown");
public static final EnumType HORSE_VARIANT = new EnumType(Fallback.WRAP, "white", "creamy", "chestnut", "brown", "black", "gray", "dark_brown");
public static final EnumType LLAMA_VARIANT = new EnumType(Fallback.CLAMP, "creamy", "white", "brown", "gray");
public static final EnumType AXOLOTL_VARIANT = new EnumType("lucy", "wild", "gold", "cyan", "blue");
// Enums with non-ordinal ids
public static final FakeEnumType RABBIT_VARIANT = new FakeEnumType(List.of("brown", "white", "black", "white_splotched", "gold", "salt"), of(99, "evil"));
// Pretty much enums, but with a resource location
public static final RegistryValueType VILLAGER_TYPE = new RegistryValueType("desert", "jungle", "plains", "savanna", "snow", "swamp", "taiga");
public static final RegistryValueType POTION = new RegistryValueType("water", "mundane", "thick", "awkward", "night_vision", "long_night_vision", "invisibility", "long_invisibility", "leaping", "long_leaping", "strong_leaping", "fire_resistance", "long_fire_resistance", "swiftness", "long_swiftness", "strong_swiftness", "slowness", "long_slowness", "strong_slowness", "turtle_master", "long_turtle_master", "strong_turtle_master", "water_breathing", "long_water_breathing", "healing", "strong_healing", "harming", "strong_harming", "poison", "long_poison", "strong_poison", "regeneration", "long_regeneration", "strong_regeneration", "strength", "long_strength", "strong_strength", "weakness", "long_weakness", "luck", "slow_falling", "long_slow_falling", "wind_charged", "weaving", "oozing", "infested");
public static final RegistryValueType MOB_EFFECT = new RegistryValueType("speed", "slowness", "haste", "mining_fatigue", "strength", "instant_health", "instant_damage", "jump_boost", "nausea", "regeneration", "resistance", "fire_resistance", "water_breathing", "invisibility", "blindness", "night_vision", "hunger", "weakness", "poison", "wither", "health_boost", "absorption", "saturation", "glowing", "levitation", "luck", "unluck", "slow_falling", "conduit_power", "dolphins_grace", "bad_omen", "hero_of_the_village", "darkness", "trial_omen", "raid_omen", "wind_charged", "weaving", "oozing", "infested");
}
@@ -22,24 +22,32 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
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.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
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 equipOnInteract) {
boolean swappable, boolean damageOnHurt, boolean equipOnInteract,
boolean canBeSheared, Holder<SoundEvent> shearingSound) implements Rewritable {
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 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, final boolean equipOnInteract) {
this(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract, false, Holder.of(0));
}
public static final Type<Equippable> TYPE1_21_2 = new Type<>(Equippable.class) {
@Override
public Equippable read(final ByteBuf buffer) {
@@ -94,9 +102,43 @@ public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Null
buffer.writeBoolean(value.equipOnInteract());
}
};
public static final Type<Equippable> TYPE1_21_6 = 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();
final boolean canBeSheared = buffer.readBoolean();
final Holder<SoundEvent> shearingSound = Types.SOUND_EVENT.read(buffer);
return new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract, canBeSheared, shearingSound);
}
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, 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());
buffer.writeBoolean(value.canBeSheared());
Types.SOUND_EVENT.write(buffer, value.shearingSound());
}
};
@Override
public Equippable rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = SoundEvent.rewriteHolder(this.soundEvent, Rewritable.soundRewriteFunction(protocol, clientbound));
final Holder<SoundEvent> shearingSound = SoundEvent.rewriteHolder(this.shearingSound, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent && shearingSound == this.shearingSound ? this : new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt, equipOnInteract, canBeSheared, shearingSound);
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -74,6 +75,13 @@ public abstract class Filterable<T> {
optionalElementType.write(buffer, value.filtered());
}
@Override
public void write(final Ops ops, final F value) {
ops.writeMap(map -> map
.write("raw", elementType, value.raw())
.writeOptional("filtered", elementType, value.filtered()));
}
protected abstract F create(T raw, T filtered);
}
}
@@ -23,12 +23,16 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import org.checkerframework.checker.nullness.qual.Nullable;
public final class FilterableComponent extends Filterable<Tag> {
public final class FilterableComponent extends Filterable<Tag> implements Copyable, Rewritable {
public static final Type<FilterableComponent> TYPE = new FilterableType<>(Types.TAG, Types.OPTIONAL_TAG, FilterableComponent.class) {
@Override
@@ -41,4 +45,21 @@ public final class FilterableComponent extends Filterable<Tag> {
public FilterableComponent(final Tag raw, @Nullable final Tag filtered) {
super(raw, filtered);
}
@Override
public FilterableComponent rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (protocol.getComponentRewriter() == null) {
return this;
}
final FilterableComponent copy = copy();
protocol.getComponentRewriter().processTag(connection, copy.raw());
protocol.getComponentRewriter().processTag(connection, copy.filtered());
return copy;
}
@Override
public FilterableComponent copy() {
return new FilterableComponent(raw().copy(), filtered() != null ? filtered().copy() : null);
}
}
@@ -22,13 +22,18 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.ArrayUtil;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boolean hasTrail, boolean hasTwinkle) implements Copyable {
public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boolean hasTrail,
boolean hasTwinkle) implements Copyable {
public static final String[] SHAPES = {"small_ball", "large_ball", "star", "creeper", "burst"};
public static final Type<FireworkExplosion> TYPE = new Type<>(FireworkExplosion.class) {
@Override
public FireworkExplosion read(final ByteBuf buffer) {
@@ -48,11 +53,21 @@ public record FireworkExplosion(int shape, int[] colors, int[] fadeColors, boole
buffer.writeBoolean(value.hasTrail);
buffer.writeBoolean(value.hasTwinkle);
}
@Override
public void write(final Ops ops, final FireworkExplosion value) {
ops.writeMap(map -> map
.write("shape", Types.STRING, SHAPES[value.shape])
.writeOptional("colors", new ArrayType<>(Types.INT), ArrayUtil.boxedArray(value.colors), new Integer[0])
.writeOptional("fade_colors", new ArrayType<>(Types.INT), ArrayUtil.boxedArray(value.fadeColors), new Integer[0])
.writeOptional("has_trail", Types.BOOLEAN, value.hasTrail, false)
.writeOptional("has_twinkle", Types.BOOLEAN, value.hasTwinkle, false));
}
};
public static final Type<FireworkExplosion[]> ARRAY_TYPE = new ArrayType<>(TYPE);
@Override
public FireworkExplosion copy() {
return new FireworkExplosion(shape, copy(colors), copy(fadeColors), hasTrail, hasTwinkle);
return new FireworkExplosion(shape, Copyable.copy(colors), Copyable.copy(fadeColors), hasTrail, hasTwinkle);
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
@@ -42,10 +43,17 @@ public record Fireworks(int flightDuration, FireworkExplosion[] explosions) impl
Types.VAR_INT.writePrimitive(buffer, value.flightDuration);
FireworkExplosion.ARRAY_TYPE.write(buffer, value.explosions);
}
@Override
public void write(final Ops ops, final Fireworks value) {
ops.writeMap(map -> map
.writeOptional("flight_duration", Types.UNSIGNED_BYTE, (short) value.flightDuration, (short) 0)
.writeOptional("explosions", FireworkExplosion.ARRAY_TYPE, value.explosions, new FireworkExplosion[0]));
}
};
@Override
public Fireworks copy() {
return new Fireworks(flightDuration, copy(explosions));
return new Fireworks(flightDuration, Copyable.copy(explosions));
}
}
@@ -26,7 +26,7 @@ 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.ArrayType;
import com.viaversion.viaversion.api.type.types.version.Types1_21;
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -61,7 +61,7 @@ public record FoodProperties1_20_5(int nutrition, float saturationModifier, bool
final float saturationModifier = buffer.readFloat();
final boolean canAlwaysEat = buffer.readBoolean();
final float eatSeconds = buffer.readFloat();
final Item usingConvertsTo = Types1_21.OPTIONAL_ITEM.read(buffer);
final Item usingConvertsTo = VersionedTypes.V1_21.optionalItem.read(buffer);
final FoodEffect[] possibleEffects = FoodEffect.ARRAY_TYPE.read(buffer);
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo, possibleEffects);
}
@@ -72,14 +72,14 @@ public record FoodProperties1_20_5(int nutrition, float saturationModifier, bool
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
buffer.writeFloat(value.eatSeconds);
Types1_21.OPTIONAL_ITEM.write(buffer, value.usingConvertsTo);
VersionedTypes.V1_21.optionalItem.write(buffer, value.usingConvertsTo);
FoodEffect.ARRAY_TYPE.write(buffer, value.possibleEffects);
}
};
@Override
public FoodProperties1_20_5 copy() {
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo == null ? null : usingConvertsTo.copy(), copy(possibleEffects));
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo == null ? null : usingConvertsTo.copy(), Copyable.copy(possibleEffects));
}
public record FoodEffect(PotionEffect effect, float probability) {
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
@@ -43,5 +44,13 @@ public record FoodProperties1_21_2(int nutrition, float saturationModifier, bool
buffer.writeFloat(value.saturationModifier);
buffer.writeBoolean(value.canAlwaysEat);
}
@Override
public void write(final Ops ops, final FoodProperties1_21_2 value) {
ops.writeMap(map -> map
.write("nutrition", Types.VAR_INT, value.nutrition)
.write("saturation", Types.FLOAT, value.saturationModifier)
.writeOptional("can_always_eat", Types.BOOLEAN, value.canAlwaysEat, false));
}
};
}
@@ -22,14 +22,16 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, float range) {
public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, float range) implements Rewritable {
public static final HolderType<Instrument1_20_5> TYPE = new HolderType<>() {
@Override
@@ -48,8 +50,9 @@ public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, f
}
};
public Instrument1_20_5 rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
@Override
public Instrument1_20_5 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = SoundEvent.rewriteHolder(this.soundEvent, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new Instrument1_20_5(soundEvent, useDuration, range);
}
}
@@ -23,16 +23,19 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.minecraft.SoundEvent;
import com.viaversion.viaversion.api.protocol.Protocol;
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 com.viaversion.viaversion.util.Rewritable;
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) implements Copyable {
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range,
Tag description) implements Copyable, Rewritable {
public static final HolderType<Instrument1_21_2> TYPE = new HolderType<>() {
@Override
@@ -54,8 +57,9 @@ public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration,
};
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);
@Override
public Instrument1_21_2 rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = SoundEvent.rewriteHolder(this.soundEvent, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, description);
}
@@ -23,17 +23,19 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.connection.UserConnection;
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.protocol.Protocol;
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.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record JukeboxPlayable(EitherHolder<JukeboxSong> song, boolean showInTooltip) {
public record JukeboxPlayable(EitherHolder<JukeboxSong> song, boolean showInTooltip) implements Rewritable {
public JukeboxPlayable(final Holder<JukeboxSong> song, final boolean showInTooltip) {
this(EitherHolder.of(song), showInTooltip);
@@ -70,7 +72,8 @@ public record JukeboxPlayable(EitherHolder<JukeboxSong> song, boolean showInTool
}
};
public JukeboxPlayable rewrite(final Int2IntFunction soundIdRewriteFunction) {
@Override
public JukeboxPlayable rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (this.song.hasKey()) {
return this;
}
@@ -80,12 +83,12 @@ public record JukeboxPlayable(EitherHolder<JukeboxSong> song, boolean showInTool
return this;
}
final JukeboxSong rewrittenSong = songHolder.value().rewrite(soundIdRewriteFunction);
final JukeboxSong rewrittenSong = songHolder.value().rewrite(connection, protocol, clientbound);
return rewrittenSong == songHolder.value() ? this : new JukeboxPlayable(Holder.of(rewrittenSong), showInTooltip);
}
public record JukeboxSong(Holder<SoundEvent> soundEvent, Tag description,
float lengthInSeconds, int comparatorOutput) {
float lengthInSeconds, int comparatorOutput) implements Rewritable {
public static final HolderType<JukeboxSong> TYPE = new HolderType<>() {
@Override
@@ -106,8 +109,9 @@ public record JukeboxPlayable(EitherHolder<JukeboxSong> song, boolean showInTool
}
};
public JukeboxSong rewrite(final Int2IntFunction soundIdRewriteFunction) {
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
@Override
public JukeboxSong rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final Holder<SoundEvent> soundEvent = SoundEvent.rewriteHolder(this.soundEvent, Rewritable.soundRewriteFunction(protocol, clientbound));
return soundEvent == this.soundEvent ? this : new JukeboxSong(soundEvent, description, lengthInSeconds, comparatorOutput);
}
}
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.GlobalBlockPosition;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
@@ -43,6 +44,12 @@ public record LodestoneTracker(@Nullable GlobalBlockPosition position, boolean t
Types.OPTIONAL_GLOBAL_POSITION.write(buffer, value.position);
buffer.writeBoolean(value.tracked);
}
};
@Override
public void write(final Ops ops, final LodestoneTracker value) {
ops.writeMap(map -> map
.writeOptional("target", Types.GLOBAL_POSITION, value.position)
.writeOptional("tracked", Types.BOOLEAN, value.tracked, true));
}
};
}
@@ -22,13 +22,15 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public final class PotDecorations implements Copyable {
public final class PotDecorations implements Copyable, Rewritable {
public static final Type<PotDecorations> TYPE = new Type<>(PotDecorations.class) {
@Override
@@ -76,16 +78,17 @@ public final class PotDecorations implements Copyable {
return index < 0 || index >= itemIds.length ? -1 : itemIds[index];
}
public PotDecorations rewrite(final Int2IntFunction idRewriteFunction) {
@Override
public PotDecorations rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final int[] newItems = new int[itemIds.length];
for (int i = 0; i < itemIds.length; i++) {
newItems[i] = idRewriteFunction.applyAsInt(itemIds[i]);
newItems[i] = Rewritable.rewriteItem(protocol, clientbound, itemIds[i]);
}
return new PotDecorations(newItems);
}
@Override
public PotDecorations copy() {
return new PotDecorations(copy(itemIds));
return new PotDecorations(Copyable.copy(itemIds));
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
@@ -85,10 +86,19 @@ public record PotionContents(@Nullable Integer potion, @Nullable Integer customC
PotionEffect.ARRAY_TYPE.write(buffer, value.customEffects);
Types.OPTIONAL_STRING.write(buffer, value.customName);
}
@Override
public void write(final Ops ops, final PotionContents value) {
ops.writeMap(map -> map
.writeOptional("potion", EnumTypes.POTION, value.potion)
.writeOptional("custom_color", Types.INT, value.customColor)
.writeOptional("custom_effects", PotionEffect.ARRAY_TYPE, value.customEffects, new PotionEffect[0])
.writeOptional("custom_name", Types.STRING, value.customName));
}
};
@Override
public PotionContents copy() {
return new PotionContents(potion, customColor, copy(customEffects), customName);
return new PotionContents(potion, customColor, Copyable.copy(customEffects), customName);
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
@@ -42,6 +43,13 @@ public record PotionEffect(int effect, PotionEffectData effectData) {
Types.VAR_INT.writePrimitive(buffer, value.effect);
PotionEffectData.TYPE.write(buffer, value.effectData);
}
@Override
public void write(final Ops ops, final PotionEffect value) {
ops.writeMap(map -> map
.write("id", EnumTypes.MOB_EFFECT, value.effect)
.writeInlinedMap(PotionEffectData.TYPE, value.effectData));
}
};
public static final Type<PotionEffect[]> ARRAY_TYPE = new ArrayType<>(TYPE);
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
@@ -52,6 +53,17 @@ public record PotionEffectData(int amplifier, int duration, boolean ambient, boo
buffer.writeBoolean(value.showIcon);
OPTIONAL_TYPE.write(buffer, value.hiddenEffect);
}
@Override
public void write(final Ops ops, final PotionEffectData value) {
ops.writeMap(map -> map
.writeOptional("amplifier", Types.UNSIGNED_BYTE, (short) value.amplifier, (short) 0)
.writeOptional("duration", Types.INT, value.duration, 0)
.writeOptional("ambient", Types.BOOLEAN, value.ambient, false)
.writeOptional("show_particles", Types.BOOLEAN, value.showParticles, true)
.writeOptional("show_icon", Types.BOOLEAN, value.showIcon)
.writeOptional("hidden_effect", TYPE, value.hiddenEffect));
}
};
public static final Type<PotionEffectData> OPTIONAL_TYPE = new OptionalType<>(TYPE) {
};
@@ -22,14 +22,16 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.EitherHolder;
import com.viaversion.viaversion.api.minecraft.Holder;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.misc.EitherHolderType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ProvidesTrimMaterial(EitherHolder<ArmorTrimMaterial> material) {
public record ProvidesTrimMaterial(EitherHolder<ArmorTrimMaterial> material) implements Rewritable {
public static final Type<ProvidesTrimMaterial> TYPE = new Type<>(ProvidesTrimMaterial.class) {
@@ -45,12 +47,13 @@ public record ProvidesTrimMaterial(EitherHolder<ArmorTrimMaterial> material) {
}
};
public ProvidesTrimMaterial rewrite(final Int2IntFunction itemIdRewriter) {
@Override
public ProvidesTrimMaterial rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (material.hasKey() || material.holder().hasId()) {
return this;
}
final ArmorTrimMaterial trimMaterial = material.holder().value();
return new ProvidesTrimMaterial(EitherHolder.of(Holder.of(trimMaterial.rewrite(itemIdRewriter))));
return new ProvidesTrimMaterial(EitherHolder.of(Holder.of(trimMaterial.rewrite(connection, protocol, clientbound))));
}
}
@@ -22,12 +22,15 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int damagePerBlock, boolean canDestroyBlocksInCreative) {
public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int damagePerBlock,
boolean canDestroyBlocksInCreative) implements Rewritable {
public ToolProperties(final ToolRule[] rules, final float defaultMiningSpeed, final int damagePerBlock) {
this(rules, defaultMiningSpeed, damagePerBlock, false);
@@ -68,10 +71,11 @@ public record ToolProperties(ToolRule[] rules, float defaultMiningSpeed, int dam
}
};
public ToolProperties rewrite(final Int2IntFunction blockIdRewriter) {
@Override
public ToolProperties rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
final ToolRule[] rules = new ToolRule[this.rules.length];
for (int i = 0; i < rules.length; i++) {
rules[i] = this.rules[i].rewrite(blockIdRewriter);
rules[i] = this.rules[i].rewrite(connection, protocol, clientbound);
}
return new ToolProperties(rules, defaultMiningSpeed, damagePerBlock, canDestroyBlocksInCreative);
}
@@ -22,15 +22,18 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.HolderSet;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.ArrayType;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import org.checkerframework.checker.nullness.qual.Nullable;
public record ToolRule(HolderSet blocks, @Nullable Float speed, @Nullable Boolean correctForDrops) {
public record ToolRule(HolderSet blocks, @Nullable Float speed,
@Nullable Boolean correctForDrops) implements Rewritable {
public static final Type<ToolRule> TYPE = new Type<>(ToolRule.class) {
@Override
@@ -50,7 +53,8 @@ public record ToolRule(HolderSet blocks, @Nullable Float speed, @Nullable Boolea
};
public static final Type<ToolRule[]> ARRAY_TYPE = new ArrayType<>(TYPE);
public ToolRule rewrite(final Int2IntFunction blockIdRewriter) {
return blocks.hasIds() ? new ToolRule(blocks.rewrite(blockIdRewriter), speed, correctForDrops) : this;
@Override
public ToolRule rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
return blocks.hasIds() ? new ToolRule(blocks.rewrite(Rewritable.blockRewriteFunction(protocol, clientbound)), speed, correctForDrops) : this;
}
}
@@ -22,15 +22,19 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
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...
IntSortedSet hiddenComponents) implements Rewritable { // Keeping the ids raw makes this less annoying to deal with...
public static final Type<TooltipDisplay> TYPE = new Type<>(TooltipDisplay.class) {
@@ -53,16 +57,25 @@ public record TooltipDisplay(boolean hideTooltip,
Types.VAR_INT.writePrimitive(buffer, hiddenComponent);
}
}
@Override
public void write(final Ops ops, final TooltipDisplay value) {
final Key[] hiddenComponents = value.hiddenComponents.intStream().mapToObj(id -> ops.context().registryAccess().dataComponentType(id)).toArray(Key[]::new);
ops.writeMap(map -> map
.writeOptional("hide_tooltip", Types.BOOLEAN, value.hideTooltip, false)
.writeOptional("hidden_components", Types.RESOURCE_LOCATION_ARRAY, hiddenComponents, new Key[0]));
}
};
public TooltipDisplay rewrite(final Int2IntFunction idRewriter) {
@Override
public TooltipDisplay rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (hiddenComponents.isEmpty()) {
return this;
}
final IntSortedSet newHiddenComponents = new IntLinkedOpenHashSet();
for (final int hiddenComponent : hiddenComponents) {
newHiddenComponents.add(idRewriter.applyAsInt(hiddenComponent));
newHiddenComponents.add(Rewritable.rewriteDataComponentType(protocol, clientbound, hiddenComponent));
}
return new TooltipDisplay(hideTooltip, newHiddenComponents);
}
@@ -0,0 +1,83 @@
/*
* 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.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import java.util.Arrays;
// Completely cooked packed id instead of just using an ordinal. Not even consistent enough for FakeEnumType
public record TropicalFishPattern(int packedId) {
public static final Type<TropicalFishPattern> TYPE = new Type<>(TropicalFishPattern.class) {
@Override
public TropicalFishPattern read(final ByteBuf buffer) {
final int packedId = Types.VAR_INT.readPrimitive(buffer);
return new TropicalFishPattern(packedId);
}
@Override
public void write(final ByteBuf buffer, final TropicalFishPattern value) {
Types.VAR_INT.writePrimitive(buffer, value.packedId);
}
@Override
public void write(final Ops ops, final TropicalFishPattern value) {
final Pattern pattern = Arrays.stream(Pattern.values()).filter(e -> e.packedId == value.packedId).findAny().orElse(Pattern.KOB);
ops.write(Types.STRING, pattern.key);
}
};
public int sizeId() {
return packedId & 0xFF;
}
public int sizeSpecificId() {
return packedId >> 8;
}
private enum Pattern {
KOB("kob", 0, 0),
SUNSTREAK("sunstreak", 0, 1),
SNOOPER("snooper", 0, 2),
DASHER("dasher", 0, 3),
BRINELY("brinely", 0, 4),
SPOTTY("spotty", 0, 5),
FLOPPER("flopper", 1, 0),
STRIPEY("stripey", 1, 1),
GLITTER("glitter", 1, 2),
BLOCKFISH("blockfish", 1, 3),
BETTY("betty", 1, 4),
CLAYFISH("clayfish", 1, 5);
private final String key;
private final int packedId;
Pattern(final String key, final int sizeId, final int sizeSpecificId) {
this.key = key;
this.packedId = sizeId | (sizeSpecificId << 8);
}
}
}
@@ -22,13 +22,17 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Rewritable;
import io.netty.buffer.ByteBuf;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public record UseCooldown(float seconds, @Nullable String cooldownGroup) {
public record UseCooldown(float seconds, @Nullable String cooldownGroup) implements Rewritable {
public static final Type<UseCooldown> TYPE = new Type<>(UseCooldown.class) {
@Override
@@ -43,14 +47,23 @@ public record UseCooldown(float seconds, @Nullable String cooldownGroup) {
buffer.writeFloat(value.seconds());
Types.OPTIONAL_STRING.write(buffer, value.cooldownGroup());
}
@Override
public void write(final Ops ops, final UseCooldown value) {
final Key cooldownGroup = value.cooldownGroup != null ? Key.of(value.cooldownGroup) : null;
ops.writeMap(map -> map
.write("seconds", Types.FLOAT, value.seconds())
.writeOptional("cooldown_group", Types.RESOURCE_LOCATION, cooldownGroup));
}
};
public UseCooldown rewrite(final Function<String, String> idRewriter) {
@Override
public UseCooldown rewrite(final UserConnection connection, final Protocol<?, ?, ?, ?> protocol, final boolean clientbound) {
if (cooldownGroup == null) {
return this;
}
final String mappedCooldownGroup = idRewriter.apply(cooldownGroup);
final String mappedCooldownGroup = Rewritable.rewriteItem(protocol, clientbound, cooldownGroup);
return new UseCooldown(seconds, mappedCooldownGroup);
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
@@ -41,5 +42,12 @@ public record Weapon(int itemDamagePerAttack, float disableBlockingForSeconds) {
Types.VAR_INT.writePrimitive(buffer, value.itemDamagePerAttack());
buffer.writeFloat(value.disableBlockingForSeconds());
}
@Override
public void write(final Ops ops, final Weapon weapon) {
ops.writeMap(map -> map
.writeOptional("item_damage_per_attack", Types.INT, weapon.itemDamagePerAttack, 1)
.writeOptional("disable_blocking_for_seconds", Types.FLOAT, weapon.disableBlockingForSeconds, 0F));
}
};
}
@@ -0,0 +1,53 @@
/*
* 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.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
import io.netty.buffer.ByteBuf;
public record WritableBook(FilterableString[] pages) implements Copyable {
public static final Type<WritableBook> TYPE = new Type<>(WritableBook.class) {
@Override
public WritableBook read(final ByteBuf buffer) {
return new WritableBook(FilterableString.ARRAY_TYPE.read(buffer));
}
@Override
public void write(final ByteBuf buffer, final WritableBook value) {
FilterableString.ARRAY_TYPE.write(buffer, value.pages);
}
@Override
public void write(final Ops ops, final WritableBook writableBook) {
ops.writeMap(map -> map.writeOptional("pages", FilterableString.ARRAY_TYPE, writableBook.pages, new FilterableString[0]));
}
};
@Override
public WritableBook copy() {
return new WritableBook(Copyable.copy(pages));
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.minecraft.item.data;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.Copyable;
@@ -49,10 +50,20 @@ public record WrittenBook(FilterableString title, String author, int generation,
FilterableComponent.ARRAY_TYPE.write(buffer, value.pages);
buffer.writeBoolean(value.resolved);
}
@Override
public void write(final Ops ops, final WrittenBook value) {
ops.writeMap(map -> map
.write("title", FilterableString.TYPE, value.title)
.write("author", Types.STRING, value.author)
.writeOptional("generation", Types.INT, value.generation, 0)
.writeOptional("pages", FilterableComponent.ARRAY_TYPE, value.pages, new FilterableComponent[0])
.writeOptional("resolved", Types.BOOLEAN, value.resolved, false));
}
};
@Override
public WrittenBook copy() {
return new WrittenBook(title, author, generation, copy(pages), resolved);
return new WrittenBook(title, author, generation, Copyable.copy(pages), resolved);
}
}
@@ -26,6 +26,7 @@ import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
@@ -247,6 +248,10 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
connection.addEntityTracker(this.getClass(), tracker);
}
protected void addItemHasher(UserConnection connection, ItemHasher hasher) {
connection.addItemHasher(this.getClass(), hasher);
}
protected PacketTypesProvider<CU, CM, SM, SU> createPacketTypesProvider() {
return new SimplePacketTypesProvider<>(
packetTypeMap(unmappedClientboundPacketType, unmappedClientboundPacketType),
@@ -39,6 +39,7 @@ import com.viaversion.viaversion.api.rewriter.ItemRewriter;
import com.viaversion.viaversion.api.rewriter.ParticleRewriter;
import com.viaversion.viaversion.api.rewriter.TagRewriter;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.types.version.VersionedTypesHolder;
import com.viaversion.viaversion.exception.CancelException;
import com.viaversion.viaversion.exception.InformativeException;
import com.viaversion.viaversion.util.ProtocolLogger;
@@ -393,10 +394,35 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
return null;
}
/**
* Returns the protocol's component rewriter if present.
*
* @return component rewriter
*/
default @Nullable ComponentRewriter getComponentRewriter() {
return null;
}
/**
* Returns types which are initialized during protocol loading in {@link #loadMappingData()}.
* <p>
* Used in various rewriters starting with 1.21.
*
* @return versioned types
*/
default @Nullable VersionedTypesHolder types() {
return null;
}
/**
* Similar to {@link #types()}, but for the mapped types.
*
* @return versioned types
*/
default @Nullable VersionedTypesHolder mappedTypes() {
return null;
}
/**
* Returns whether this protocol is a base protocol.
*
@@ -89,6 +89,8 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
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 v1_21_6 = register(771, "1.21.6");
public static final ProtocolVersion v1_21_7 = register(772, "1.21.7");
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
static {
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.rewriter;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.item.HashedItem;
import com.viaversion.viaversion.api.minecraft.item.Item;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.type.Type;
@@ -50,6 +51,17 @@ public interface ItemRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter<T
@Nullable
Item handleItemToServer(UserConnection connection, @Nullable Item item);
/**
* Returns the rewritten item, which may or may not be the same given HashedItem instance.
* <p>
* Used starting with 1.21.6.
*
* @param connection user connection
* @param item hashed item
* @return rewritten hashed item
*/
HashedItem handleHashedItem(UserConnection connection, HashedItem item);
/**
* Returns the item type of the current protocol.
*
@@ -0,0 +1,31 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2025 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.type;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
@FunctionalInterface
public interface CodecWriter<T> {
void write(Ops ops, T value);
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -47,4 +48,9 @@ public abstract class OptionalType<T> extends Type<T> {
type.write(buffer, value);
}
}
@Override
public void write(final Ops ops, final T value) {
type.write(ops, value);
}
}
@@ -22,13 +22,15 @@
*/
package com.viaversion.viaversion.api.type;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
/**
* Type for buffer reading and writing.
*
* @param <T> read/written type
* @see Types
*/
public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T>, CodecWriter<T> {
/* Actual Class */
private final Class<? super T> outputClass;
@@ -58,7 +60,12 @@ public abstract class Type<T> implements ByteBufReader<T>, ByteBufWriter<T> {
* @return type name
*/
public String getTypeName() {
return typeName != null && !typeName.isEmpty() ? typeName : this.getClass().getSimpleName();
return typeName != null && !typeName.isEmpty() ? typeName : this.getClass().getName();
}
@Override
public void write(Ops ops, T value) {
throw new UnsupportedOperationException("Write operation not supported for type: " + getTypeName());
}
/**
@@ -41,7 +41,9 @@ 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.ChunkSection;
import com.viaversion.viaversion.api.minecraft.chunks.Heightmap;
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
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;
@@ -76,7 +78,15 @@ 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.ChunkSectionType1_13;
import com.viaversion.viaversion.api.type.types.chunk.ChunkSectionType1_16;
import com.viaversion.viaversion.api.type.types.chunk.ChunkSectionType1_8;
import com.viaversion.viaversion.api.type.types.chunk.ChunkSectionType1_9;
import com.viaversion.viaversion.api.type.types.chunk.HeightmapType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType1_12;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType1_8;
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType1_9;
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;
@@ -97,14 +107,21 @@ import com.viaversion.viaversion.api.type.types.misc.CompoundTagType;
import com.viaversion.viaversion.api.type.types.misc.GameProfileType;
import com.viaversion.viaversion.api.type.types.misc.HolderSetType;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.api.type.types.misc.KeyType;
import com.viaversion.viaversion.api.type.types.misc.LengthPrefixedTagType;
import com.viaversion.viaversion.api.type.types.misc.NamedCompoundTagType;
import com.viaversion.viaversion.api.type.types.misc.PlayerMessageSignatureType;
import com.viaversion.viaversion.api.type.types.misc.ProfileKeyType;
import com.viaversion.viaversion.api.type.types.misc.ProfilePropertyType;
import com.viaversion.viaversion.api.type.types.misc.SoundEventType;
import com.viaversion.viaversion.api.type.types.misc.TagKeyType;
import com.viaversion.viaversion.api.type.types.misc.TagType;
import com.viaversion.viaversion.api.type.types.misc.TextComponentTagType;
import com.viaversion.viaversion.api.type.types.misc.VillagerDataType;
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
import com.viaversion.viaversion.util.Key;
import com.viaversion.viaversion.util.Unit;
import java.util.List;
import java.util.UUID;
/**
@@ -162,6 +179,11 @@ public final class Types {
/* MC Types */
public static final Type<byte[]> SERVERBOUND_CUSTOM_PAYLOAD_DATA = new RemainingBytesType(Short.MAX_VALUE);
public static final Type<Key> RESOURCE_LOCATION = new KeyType();
public static final Type<Key> OPTIONAL_RESOURCE_LOCATION = new KeyType.OptionalKeyType();
public static final Type<Key[]> RESOURCE_LOCATION_ARRAY = new ArrayType<>(RESOURCE_LOCATION);
public static final Type<Key> TAG_KEY = new TagKeyType();
public static final Type<BlockPosition> BLOCK_POSITION1_8 = new BlockPositionType1_8();
public static final Type<BlockPosition> OPTIONAL_POSITION1_8 = new BlockPositionType1_8.OptionalBlockPositionType();
public static final Type<BlockPosition> BLOCK_POSITION1_14 = new BlockPositionType1_14();
@@ -179,11 +201,18 @@ public final class Types {
public static final Type<Tag> TAG = new TagType();
public static final Type<Tag[]> TAG_ARRAY = new ArrayType<>(TAG);
public static final Type<Tag> OPTIONAL_TAG = new TagType.OptionalTagType();
public static final Type<Tag> TEXT_COMPONENT_TAG = new TextComponentTagType(); // only strictly needed for hashing
public static final Type<Tag> CUSTOM_CLICK_ACTION_TAG = new LengthPrefixedTagType(65536);
public static final Type<GlobalBlockPosition> GLOBAL_POSITION = new GlobalBlockPositionType();
public static final Type<GlobalBlockPosition> OPTIONAL_GLOBAL_POSITION = new GlobalBlockPositionType.OptionalGlobalPositionType();
public static final Type<ChunkPosition> CHUNK_POSITION = new ChunkPositionType();
public static final Type<ChunkSection> CHUNK_SECTION1_8 = new ChunkSectionType1_8();
public static final Type<ChunkSection> CHUNK_SECTION1_9 = new ChunkSectionType1_9();
public static final Type<ChunkSection> CHUNK_SECTION1_13 = new ChunkSectionType1_13();
public static final Type<ChunkSection> CHUNK_SECTION1_16 = new ChunkSectionType1_16();
public static final Type<BlockEntity> BLOCK_ENTITY1_18 = new BlockEntityType1_18();
public static final Type<BlockEntity> BLOCK_ENTITY1_20_2 = new BlockEntityType1_20_2();
@@ -195,6 +224,8 @@ public final class Types {
public static final Type<VillagerData> VILLAGER_DATA = new VillagerDataType();
public static final Type<GameProfile> GAME_PROFILE = new GameProfileType();
public static final Type<GameProfile.Property> PROFILE_PROPERTY = new ProfilePropertyType();
public static final Type<GameProfile.Property[]> PROFILE_PROPERTY_ARRAY = new ArrayType<>(PROFILE_PROPERTY);
public static final Type<ProfileKey> PROFILE_KEY = new ProfileKeyType();
public static final Type<ProfileKey> OPTIONAL_PROFILE_KEY = new ProfileKeyType.OptionalProfileKeyType();
@@ -222,6 +253,14 @@ public final class Types {
public static final Type<Heightmap> HEIGHTMAP = new HeightmapType();
public static final Type<Heightmap[]> HEIGHTMAP_ARRAY = new ArrayType<>(HEIGHTMAP);
public static final Type<EntityData> ENTITY_DATA1_8 = new EntityDataType1_8();
public static final Type<EntityData> ENTITY_DATA1_9 = new EntityDataType1_9();
public static final Type<EntityData> ENTITY_DATA1_12 = new EntityDataType1_12();
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_8 = new EntityDataListType(ENTITY_DATA1_8);
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_9 = new EntityDataListType(ENTITY_DATA1_9);
public static final Type<List<EntityData>> ENTITY_DATA_LIST1_12 = new EntityDataListType(ENTITY_DATA1_12);
// No longer used past 1.20.2
public static final Type<Item> ITEM1_8 = new ItemType1_8();
public static final Type<Item> ITEM1_13 = new ItemType1_13();
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
@@ -91,4 +92,13 @@ public class ArrayType<T> extends Type<T[]> {
elementType.write(buffer, o);
}
}
@Override
public void write(final Ops ops, final T[] value) {
ops.writeList(list -> {
for (T element : value) {
list.write(elementType, element);
}
});
}
}
@@ -36,7 +36,7 @@ public class BitSetType extends Type<BitSet> {
public BitSetType(final int length) {
super(BitSet.class);
this.length = length;
this.bytesLength = -Math.floorDiv(-length, 8); // Ceiled quotient
this.bytesLength = (int) Math.ceil(length / 8D);
}
@Override
@@ -48,8 +48,8 @@ public class BitSetType extends Type<BitSet> {
@Override
public void write(ByteBuf buffer, BitSet object) {
Preconditions.checkArgument(object.length() <= length, "BitSet of length " + object.length() + " larger than max length " + length);
Preconditions.checkArgument(object.length() <= length, "BitSet of length %s larger than max length %s", object.length(), length);
final byte[] bytes = object.toByteArray();
buffer.writeBytes(Arrays.copyOf(bytes, bytesLength));
buffer.writeBytes(bytes.length == bytesLength ? bytes : Arrays.copyOf(bytes, bytesLength));
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.TypeConverter;
@@ -29,6 +30,7 @@ import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
public class BooleanType extends Type<Boolean> implements TypeConverter<Boolean> {
public BooleanType() {
super(Boolean.class);
}
@@ -52,6 +54,11 @@ public class BooleanType extends Type<Boolean> implements TypeConverter<Boolean>
return (Boolean) o;
}
@Override
public void write(final Ops ops, final Boolean value) {
ops.writeBoolean(value);
}
// Lol
public static final class OptionalBooleanType extends OptionalType<Boolean> {
@@ -23,6 +23,7 @@
package com.viaversion.viaversion.api.type.types;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
@@ -61,6 +62,11 @@ public class ByteArrayType extends Type<byte[]> {
return array;
}
@Override
public void write(final Ops ops, final byte[] value) {
ops.writeBytes(value);
}
public static final class OptionalByteArrayType extends OptionalType<byte[]> {
public OptionalByteArrayType() {
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.TypeConverter;
import io.netty.buffer.ByteBuf;
@@ -51,6 +52,11 @@ public class ByteType extends Type<Byte> implements TypeConverter<Byte> {
buffer.writeByte(object);
}
@Override
public void write(final Ops ops, final Byte value) {
ops.writeByte(value);
}
@Override
public Byte from(Object o) {
if (o instanceof Number number) {
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.TypeConverter;
import io.netty.buffer.ByteBuf;
@@ -58,6 +59,11 @@ public class DoubleType extends Type<Double> implements TypeConverter<Double> {
buffer.writeDouble(object);
}
@Override
public void write(final Ops ops, final Double value) {
ops.writeDouble(value);
}
@Override
public Double from(Object o) {
if (o instanceof Number number) {
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Unit;
import io.netty.buffer.ByteBuf;
@@ -40,4 +41,11 @@ public final class EmptyType extends Type<Unit> {
@Override
public void write(final ByteBuf buffer, final Unit value) {
}
@Override
public void write(final Ops ops, final Unit value) {
// Written as an empty map because lol
ops.writeMap(map -> {
});
}
}
@@ -0,0 +1,65 @@
/*
* 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.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.MathUtil;
public final class EnumType extends VarIntType {
private final String[] names;
private final Fallback fallback;
public EnumType(final String... names) {
this(Fallback.ZERO, names);
}
public EnumType(final Fallback fallback, final String... names) {
this.names = names;
this.fallback = fallback;
}
@Override
public void write(final Ops ops, final Integer value) {
final String name;
if (value < 0 || value >= names.length) {
name = switch (fallback) {
case ZERO -> names[0];
case WRAP -> names[Math.floorMod(value, names.length)];
case CLAMP -> names[MathUtil.clamp(value, 0, names.length - 1)];
};
} else {
name = names[value];
}
Types.STRING.write(ops, name);
}
public String[] names() {
return names;
}
public enum Fallback {
ZERO, WRAP, CLAMP
}
}
@@ -0,0 +1,72 @@
/*
* 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.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Types;
import java.util.List;
/**
* For enum types with hardcoded custom ids.
*
* @see EnumType
*/
public final class FakeEnumType extends VarIntType {
private final Entry[] entries;
public FakeEnumType(final List<String> initialNames, final Entry... remainingEntries) {
this.entries = new Entry[initialNames.size() + remainingEntries.length];
for (int i = 0; i < initialNames.size(); i++) {
this.entries[i] = Entry.of(i, initialNames.get(i));
}
System.arraycopy(remainingEntries, 0, this.entries, initialNames.size(), remainingEntries.length);
}
public FakeEnumType(final Entry... entries) {
this.entries = entries;
}
@Override
public void write(final Ops ops, final Integer value) {
Entry entry = null;
for (final Entry e : entries) {
if (e.id == value) {
entry = e;
break;
}
}
Types.STRING.write(ops, entry != null ? entry.name : entries[0].name);
}
public Entry[] entries() {
return entries;
}
public record Entry(int id, String name) {
public static Entry of(final int id, final String name) {
return new Entry(id, name);
}
}
}
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.type.types;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.OptionalType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.TypeConverter;
@@ -70,6 +71,11 @@ public class FloatType extends Type<Float> implements TypeConverter<Float> {
throw new UnsupportedOperationException();
}
@Override
public void write(final Ops ops, final Float value) {
ops.writeFloat(value);
}
public static final class OptionalFloatType extends OptionalType<Float> {
public OptionalFloatType() {
Loaded 100 of 281 files, more files were not shown because too many files have changed in this diff. Show more