Compare commits

..
Author SHA1 Message Date
FlorianMichael 0dd7dfe2f3 Handle empty items in pre 1.20.5 protocols
Maps empty items to null on read in 1.13, 1.13.2 and 1.20.2 item types and handles the empty item->null transition in 1.10->1.11
2024-06-09 15:14:45 +02:00
1257 changed files with 38675 additions and 63761 deletions

No files matched your search

-1
View File
@@ -1 +0,0 @@
@../AGENTS.md
+2 -2
View File
@@ -2,7 +2,7 @@
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
insert_final_newline = false
tab_width = 4
[*.java]
@@ -13,4 +13,4 @@ ij_java_generate_final_locals = true
ij_java_generate_final_parameters = true
[{*.json,*.yml}]
indent_size = 2
indent_size = 2
-1
View File
@@ -1,3 +1,2 @@
github: kennytv
patreon: kennytv
custom: ['https://florianreuth.de/donate']
+14 -6
View File
@@ -21,11 +21,10 @@ body:
- type: textarea
attributes:
label: Server/Client Error
label: Console Error
description: |
If you encounter warnings/errors in your console, **paste them with https://mclo.gs/ and put the paste link here**.
If the error is small/less than 10 lines, you may put it directly into this field.
**Important**: If you are kicked for `Network Protocol Error` or an encoder/decoder exception, please click the `Open Report Directory` button on your client and paste the newest disconnect file contents.
value: |
```
Put the mclo.gs link or text here.
@@ -41,7 +40,7 @@ body:
Describe the unexpected behavior.
If you want to attach screenshots, use the comment field at the bottom of the page.
placeholder: |
Example: "Placing signs on 1.21.3 causes text to disappear."
Example: "Placing signs on 1.13.2 causes text to disappear."
validations:
required: true
@@ -50,12 +49,21 @@ body:
label: Steps to Reproduce
description: |
List the steps on how we can reproduce the issue. Make sure we can easily understand what you mean with each step.
**Please always include the client version(s) with which the issue happens. Ideally also try to find out, from what specific version onward/in what version range the issue happens.**
placeholder: |
Example:
1. Login with a 1.21.3 client
1. Login with a 1.13.2 client
2. Place a sign
3. The sign text disappears
3. The sign text is displayed wrong
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: |
Describe what exactly you expected to happen.
placeholder: |
Example: "Placed sign text should not disappear."
validations:
required: true
-17
View File
@@ -1,17 +0,0 @@
version: 2
# Disabled for the time being, being done manually instead
updates:
- package-ecosystem: "github-actions"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 0
- package-ecosystem: "gradle"
cooldown:
default-days: 7
directory: "/"
schedule:
interval: "monthly"
open-pull-requests-limit: 0
-37
View File
@@ -1,37 +0,0 @@
name: Build
on: [pull_request, push, workflow_dispatch]
permissions:
contents: read
jobs:
build:
# Only run on PRs if the source branch is on a different repo. We do not need to run everything twice.
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout Repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
- name: Set up JDK 17
uses: actions/setup-java@v6.1.0
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Build with Gradle
run: ./gradlew build
- name: Upload Artifacts to GitHub
# Only upload on the preview repository as there is no CI job for it.
if: ${{ github.repository == 'ViaVersion/ViaVersionDev' && github.ref_name == 'preview' }}
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: Artifacts
path: build/libs/
if-no-files-found: error
+24
View File
@@ -0,0 +1,24 @@
name: Java CI with Gradle
on: [push, pull_request]
jobs:
build:
# Only run on PRs if the source branch is on a different repo. We do not need to run everything twice.
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v3
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Build with Gradle
run: ./gradlew build
+7 -24
View File
@@ -4,41 +4,24 @@ on:
branches:
- master
- dev
workflow_dispatch:
permissions:
contents: read
jobs:
publish:
if: github.repository_owner == 'ViaVersion'
runs-on: ubuntu-24.04
timeout-minutes: 30
runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Gradle
uses: gradle/actions/setup-gradle@v6.4.0
with:
cache-disabled: false
cache-provider: basic
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/actions/wrapper-validation@v3
- name: Set up JDK 17
uses: actions/setup-java@v6.1.0
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Build with Gradle
run: ./gradlew build
- name: Publish to Hangar
- name: Publish
env:
HANGAR_TOKEN: ${{ secrets.HANGAR_TOKEN }}
run: ./gradlew publishAllPublicationsToHangar --stacktrace
continue-on-error: true
- name: Publish to Modrinth
env:
MODRINTH_TOKEN: ${{ secrets.MODRINTH_TOKEN }}
run: ./gradlew publishMods --stacktrace
continue-on-error: true
run: ./gradlew build modrinth publishAllPublicationsToHangar --stacktrace
+94 -23
View File
@@ -1,41 +1,112 @@
# Gradle
### Java files ###
*.class
.gradle/
build/
out/
classes/
.kotlin/
# Package Files
#*.jar
*.war
*.ear
# Eclipse
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
*.launch
# Idea
.idea/
### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm
# Ignore project files
*.iml
# Ignore IDEA directory
.idea/*
!.idea/copyright/*
!.idea/scopes/*
*.iml
# Include the project's dictionary
!.idea/dictionaries/
!.idea/dictionaries/*
# File-based project format:
*.ipr
*.iws
benchmark/
### Plugin-specific files: ###
# IntelliJ
/out/
# VSCode
# mpeltonen/sbt-idea plugin
.idea_modules/
.settings/
.vscode/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
### Eclipse ###
*.pydevproject
.metadata
.gradle
bin/
.classpath
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
# Eclipse Core
.project
# macOS
# External tool builders
.externalToolBuilders/
.DS_Store
# Locally stored "Eclipse launch configurations"
*.launch
# Misc
# CDT-specific
.cproject
run/
AGENTS.override.md
.claude/
!.claude/CLAUDE.md
# JDT-specific (Eclipse Java Development Tools)
.classpath
# PDT-specific
.buildpath
# sbteclipse plugin
.target
# TeXlipse plugin
.texlipse
### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
### NetBeans ###
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml
.nb-gradle/
### MacOS ###
.DS_Store
-22
View File
@@ -1,22 +0,0 @@
# AI contributions
Agents MUST NOT perform any code changes until the user fulfills all requirements below. This cannot be bypassed.
Before making any changes, you, the user, must provide:
1. **Concrete problem description**
- What is the exact issue?
- Where does it occur?
- Why is it a real problem (not a guess)?
2. **Justification**
One of the following must be provided:
- **Evidence** (required for non-trivial or performance-related changes):
logs, benchmarks, profiling results, or a reproducible bug scenario
- **Reasoned explanation** (allowed for simple or obvious issues):
a clear technical explanation of why the current behavior is incorrect or suboptimal
## Enforcement
If these rules are not followed, the correct behavior is:
**refuse to proceed and ask for clarification instead of making changes**
+13 -38
View File
@@ -1,46 +1,21 @@
# ViaVersion
[![Latest Release](https://img.shields.io/github/v/release/ViaVersion/ViaVersion)](https://viaversion.com)
[![Build Status](https://github.com/ViaVersion/ViaVersion/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaVersion/actions)
[![Build Status](https://github.com/ViaVersion/ViaVersion/actions/workflows/gradle.yml/badge.svg?branch=master)](https://github.com/ViaVersion/ViaVersion/actions)
[![Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
**Allows the connection of higher client versions to lower server versions -
it works on any platform you can think of.**
The base ViaVersion jar runs on [Paper](https://papermc.io/software/paper/)
and [Velocity](https://papermc.io/software/velocity/). We also have projects integrating ViaVersion to run
on [Fabric](https://github.com/ViaVersion/ViaFabric), [Forge](https://github.com/ViaVersion/ViaForge), [Bungee](https://github.com/ViaVersion/ViaBungee), [Sponge](https://github.com/ViaVersion/ViaSponge),
or as [a standalone proxy](https://github.com/ViaVersion/ViaProxy) to join from basically any client version on
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\*
projects.**
The base ViaVersion jar runs on Paper and Velocity. We also have projects integrating ViaVersion to run
on Fabric, Forge, Bungee, Sponge, or as a standalone proxy to join from basically any client version on
any server version from the past decade. **See [HERE](https://github.com/ViaVersion) for an overview of the different Via\* projects.**
**Note:** While ViaVersion works reliably across all listed platforms, it has the highest performance and state accuracy on **Paper** servers and through **[ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus)** on clients, since both offer more extensive APIs and direct access to client/server state.
Supported Versions:
### Supported Versions
![Table (https://i.imgur.com/sTrVnC2.png)](https://i.imgur.com/sTrVnC2.png)
| Players joining with… | Install |
| :--- | :--- |
| **Newer** versions than the server | ViaVersion |
| **Older** versions than the server, down to 1.9 | ViaVersion + [ViaBackwards](https://github.com/ViaVersion/ViaBackwards) |
| **1.7.x – 1.8.x** | ViaVersion + [ViaBackwards](https://github.com/ViaVersion/ViaBackwards) + [ViaRewind](https://github.com/ViaVersion/ViaRewind) |
If you're stuck, try [this tool](https://viaversion.com/setup) to work out what plugins you need.
**User Docs:** [docs.viaversion.com](https://docs.viaversion.com)
Snapshot Support
----------
**ViaVersion will only be released a few days *after* a Minecraft update** unless the protocol changes of the update
were trivial. If you want early-access, usually days or even weeks before the final release, you can subscribe to
either:
- [GitHub Sponsors](https://github.com/sponsors/kennytv/sponsorships?sponsor=kennytv&tier_id=385613&preview=false) (
preferred option. Use the `/verify` command on this Discord after), or alternatively
- [Patreon](https://www.patreon.com/kennytv/membership) (see the highest tier and make sure to link Patreon to your
Discord account under Settings->Connections)
This also includes access to a private repository with the code, which will be pushed to the public repository after
the given delay on a Minecraft update.
**User Docs:** https://docs.viaversion.com/display/VIAVERSION/
Releases/Dev Builds
--------
@@ -92,8 +67,6 @@ dependencies {
If you need access to the existing protocol or platform implementations, use the parent artifact `viaversion`.
Please note the [differences in licensing](#license).
Note: If you want to make your own platform implementation of ViaVersion (and additional addons),
take a look at the [documentation](https://github.com/ViaVersion/ViaVersion/wiki/Creating-a-new-ViaVersion-platform).
Building
--------
@@ -102,21 +75,23 @@ of the `build/libs` directory.
You need JDK 17 or newer to build ViaVersion.
Mapping Files
--------------
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings). The
generated mapping output is stored [here](./common/src/main/resources/assets/viaversion).
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings).
Resources
--------
- **[Via Mappings Generator](https://github.com/ViaVersion/Mappings)**
- **[Mojang mappings](https://minecraft.wiki/w/Obfuscation_map)** (Thank you, Mojang, very cool)
- Previously: **[Burger](https://github.com/Pokechu22/Burger)** (see [PAaaS](https://github.com/Matsv/Paaas)) and **wiki.vg**
- **[wiki.vg](https://wiki.vg)** (Used for historic information regarding packet structure, we also contribute back)
- **[Burger](https://github.com/Pokechu22/Burger)** (See [PAaaS](https://github.com/Matsv/Paaas))
License
--------
The entirety of the [API directory](api) is licensed under the MIT License;
The entirety of the [API directory](api) (including the legacy API directory) is licensed under the MIT License;
see [licenses/MIT.md](licenses/MIT.md) for
details.
-10
View File
@@ -1,10 +0,0 @@
# 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).
+3 -9
View File
@@ -19,21 +19,15 @@ dependencies {
api(libs.vianbt) {
exclude("it.unimi.dsi", "fastutil")
}
api(libs.gson) {
exclude("com.google.errorprone", "error_prone_annotations")
}
api(libs.gson)
implementation(rootProject.libs.text) {
exclude("com.google.code.gson", "gson")
exclude("com.viaversion", "nbt")
}
api(libs.snakeYaml)
compileOnlyApi(libs.snakeYaml)
compileOnlyApi(libs.netty)
compileOnlyApi(libs.guava) {
exclude("com.google.errorprone", "error_prone_annotations")
exclude("org.jspecify", "jspecify")
exclude("com.google.j2objc", "j2objc-annotations")
}
compileOnlyApi(libs.guava)
compileOnlyApi(libs.checkerQual)
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -84,8 +84,4 @@ public final class Via {
Preconditions.checkArgument(manager != null, "ViaVersion has not loaded the platform yet");
return manager;
}
public static boolean isLoaded() {
return manager != null;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -66,7 +66,7 @@ public interface ViaAPI<T> {
* @return API version incremented with meaningful API changes
*/
default int apiVersion() {
return 27;
return 26;
}
/**
@@ -114,8 +114,7 @@ public interface ViaAPI<T> {
ProtocolVersion getPlayerProtocolVersion(UUID uuid);
/**
* Returns whether Via injected into this player connection. Note that this method may not work on
* clientside implementations and is generally not recommended to be used. Use {@link ConnectionManager} instead.
* Returns whether Via injected into this player connection.
*
* @param uuid uuid of the player
* @return whether Via has a cached a UserConnection for this player
@@ -123,8 +122,7 @@ public interface ViaAPI<T> {
boolean isInjected(UUID uuid);
/**
* Returns the injected UserConnection if present. Note that this method may not work on
* clientside implementations and is generally not recommended to be used. Use {@link ConnectionManager} instead.
* Returns the Via injected UserConnection if present.
*
* @param uuid uuid of the player
* @return user connection if present
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -140,13 +140,6 @@ public interface ViaManager {
*/
void addEnableListener(Runnable runnable);
/**
* Adds a runnable to be executed when ViaVersion has finished its init after the full server load.
*
* @param runnable runnable to be executed
*/
void addPostEnableListener(Runnable runnable);
/**
* Returns whether the manager has been initialized (and protocols have been loaded).
*
@@ -1,56 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.command;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.connection.UserConnection;
import java.util.UUID;
public class UserConnectionViaCommandSender implements ViaCommandSender {
private final UserConnection connection;
public UserConnectionViaCommandSender(final UserConnection connection) {
this.connection = connection;
}
@Override
public boolean hasPermission(String permission) {
return true;
}
@Override
public void sendMessage(String msg) {
Via.getPlatform().sendMessage(connection, msg);
}
@Override
public UUID getUUID() {
return connection.getProtocolInfo().getUuid();
}
@Override
public String getName() {
return connection.getProtocolInfo().getUsername();
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -66,7 +66,7 @@ public interface ViaSubCommand {
*
* @param sender Command sender
* @param args Arguments
* @return commands executed successfully if false, show usage
* @return commands executed succesfully if false, show usage
*/
boolean execute(ViaCommandSender sender, String[] args);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,18 +30,10 @@ public interface ViaVersionCommand {
* Register your own subcommand inside ViaVersion
*
* @param command Your own SubCommand instance to handle it.
* @throws IllegalArgumentException throws an exception when the subcommand already exists or if it's not valid, example: space
* @throws IllegalArgumentException throws an exception when the subcommand already exists or if it's not valid, example: spacee
*/
void registerSubCommand(ViaSubCommand command);
/**
* Removes a subcommand by name, can be used to unload default subcommands which are not supported
* on the platform.
*
* @param name Subcommand name
*/
void removeSubCommand(String name);
/**
* Check if a subcommand is registered.
*
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,27 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.configuration;
public record RateLimitConfig(boolean enabled, int maxRate, String maxRateKickMessage, int warningRate, int maxWarnings,
long trackingPeriodNanos, String warningKickMessage, String ratePlaceholder) {
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -27,7 +27,6 @@ import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.WorldIdentifiers;
import com.viaversion.viaversion.api.protocol.version.BlockedProtocolVersions;
import java.util.concurrent.TimeUnit;
public interface ViaVersionConfig extends Config {
@@ -68,16 +67,11 @@ public interface ViaVersionConfig extends Config {
boolean isShowNewDeathMessages();
/**
* Get if entity data errors will be logged
* Get if metadata errors will be suppressed
*
* @return true if entity data error logging is enabled
* @return true if metadata errors suppression is enabled
*/
boolean logEntityDataErrors();
@Deprecated(forRemoval = true)
default boolean isSuppressMetadataErrors() {
return !logEntityDataErrors();
}
boolean isSuppressMetadataErrors();
/**
* Get if blocking in 1.9 &amp; 1.10 appears as a player holding a shield
@@ -153,64 +147,42 @@ public interface ViaVersionConfig extends Config {
*
* @return The number of packets a client can send per second.
*/
@Deprecated(forRemoval = true)
default int getMaxPPS() {
return getPacketTrackerConfig().maxRate();
}
int getMaxPPS();
/**
* Get the kick message sent if the user hits the max packets per second.
*
* @return Kick message, with colour codes using '&amp;amp;'
*/
@Deprecated(forRemoval = true)
default String getMaxPPSKickMessage() {
return getPacketTrackerConfig().maxRateKickMessage();
}
String getMaxPPSKickMessage();
/**
* The time in seconds that should be tracked for warnings
*
* @return Time in seconds that should be tracked for warnings
*/
@Deprecated(forRemoval = true)
default int getTrackingPeriod() {
return (int) TimeUnit.NANOSECONDS.toSeconds(getPacketTrackerConfig().trackingPeriodNanos());
}
int getTrackingPeriod();
/**
* The number of packets per second to count as a warning
*
* @return The number of packets per second to count as a warning.
*/
@Deprecated(forRemoval = true)
default int getWarningPPS() {
return getPacketTrackerConfig().warningRate();
}
int getWarningPPS();
/**
* Get the maximum number of warnings the client can have in the interval
*
* @return The number of packets a client can send per second.
*/
@Deprecated(forRemoval = true)
default int getMaxWarnings() {
return getPacketTrackerConfig().maxWarnings();
}
int getMaxWarnings();
/**
* Get the kick message sent if the user goes over the warnings in the interval
*
* @return Kick message, with colour codes using '&amp;amp;'
*/
@Deprecated(forRemoval = true)
default String getMaxWarningsKickMessage() {
return getPacketTrackerConfig().warningKickMessage();
}
RateLimitConfig getPacketTrackerConfig();
RateLimitConfig getPacketSizeTrackerConfig();
String getMaxWarningsKickMessage();
/**
* Send supported versions in the status response packet
@@ -261,7 +233,12 @@ public interface ViaVersionConfig extends Config {
*/
boolean isChunkBorderFix();
boolean isMultiReddustColorFix();
/**
* 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
@@ -293,8 +270,6 @@ public interface ViaVersionConfig extends Config {
*/
String getBlockedDisconnectMsg();
boolean logBlockedJoins();
/**
* Get the message sent to players being kicked on reload.
* Players are kicked to stop the server crashing
@@ -304,28 +279,11 @@ public interface ViaVersionConfig extends Config {
String getReloadDisconnectMsg();
/**
* Should we log warnings on issues when trying to convert data over versions?
* Should we hide errors that occur when trying to convert block and item data over versions?
*
* @return true if enabled
*/
boolean logOtherConversionWarnings();
/**
* Should we log errors that occur when trying to convert text components?
*
* @return true if enabled
*/
boolean logTextComponentConversionErrors();
@Deprecated(forRemoval = true)
default boolean isSuppressConversionWarnings() {
return !logOtherConversionWarnings();
}
@Deprecated(forRemoval = true)
default boolean isSuppressTextComponentConversionWarnings() {
return !logTextComponentConversionErrors();
}
boolean isSuppressConversionWarnings();
/**
* Should we disable the 1.13 auto-complete feature to stop spam kicks? (for any server lower than 1.13)
@@ -334,6 +292,13 @@ public interface ViaVersionConfig extends Config {
*/
boolean isDisable1_13AutoComplete();
/**
* Tries to minimize cooldown animation.
*
* @return true if enabled
*/
boolean isMinimizeCooldown();
/**
* Enable the serverside blockconnections for 1.13+ clients
*
@@ -499,69 +464,4 @@ public interface ViaVersionConfig extends Config {
* @return true if enabled
*/
boolean handleInvalidItemCount();
/**
* Backs up the original data of nested items (e.g. in containers or bundles) for 1.20.5+ clients on 1.20.4 and older servers.
*
* @return true if enabled
*/
boolean backupNestedItems();
/**
* Tries to cancel block break/place sounds sent by 1.8 servers to 1.9+ clients to prevent them from playing twice
*
* @return true if enabled
*/
boolean cancelBlockSounds();
/**
* Hides sidebar scoreboard numbers for 1.20.3+ clients on older server versions.
*
* @return true if enabled
*/
boolean hideScoreboardNumbers();
/**
* Fixes 1.21+ clients on 1.20.5 servers placing water/lava buckets at the wrong location when moving fast.
*
* @return true if enabled
*/
boolean fix1_21PlacementRotation();
/**
* If enabled, cancel swing packets sent while having an inventory opened on 1.15.2 and below servers.
* This can cause false positives with anti-cheat plugins.
*
* @return true if enabled
*/
boolean cancelSwingInInventory();
/**
* Returns the max length of error messages. Longer messages will be truncated unless in debug mode.
*
* @return the max length of error messages
*/
int maxErrorLength();
/**
* If enabled, 1.21.11+ clients on 1.8 (or older) servers will get wider entity hitboxes,
* but only when attacking with an item.
*
* @return true if enabled
*/
boolean use1_8HitboxMargin();
/**
* If enabled, ViaVersion will send the native client version to the server on connect via a plugin message.
*
* @return true if enabled
*/
boolean sendPlayerDetails();
/**
* If enabled, ViaVersion will send the native server version to a player on connect via a plugin message.
*
* @return true if enabled
*/
boolean sendServerDetails();
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,81 +28,51 @@ import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Handles injected UserConnections.
* Check {@link UserConnection#isServerSide()} and {@link UserConnection#isClientSide()} to determine the connection type.
* Handles injected UserConnections
*/
public interface ConnectionManager {
/**
* Returns if Via has injected. See above for the connection types.
* Returns if Via injected into this player connection.
*
* @param uuid player uuid
* @param playerId player uuid
* @return true if the player is handled by Via
*/
boolean hasServerConnection(UUID uuid);
boolean isClientConnected(UUID playerId);
@Deprecated
default boolean isClientConnected(UUID uuid) {
return hasServerConnection(uuid);
/**
* Frontend connections will have the UUID stored. Override this if your platform isn't always frontend.
* UUIDs can't be duplicate between frontend connections.
*
* @return true if the user is a frontend connection
*/
default boolean isFrontEnd(UserConnection connection) {
return !connection.isClientSide();
}
/**
* Returns if Via has injected. See above for the connection types.
*
* @param uuid player uuid
* @return true if the player is handled by Via
*/
boolean hasClientConnection(UUID uuid);
/**
* Returns the server UserConnection. See above for the connection types.
* Returns the frontend UserConnection from the player connected to this proxy server
* Returns null when there isn't a server or connection was not found
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
*
* @return server UserConnection of the player or null
* @return frontend UserConnection of the player connected to this proxy server
*/
@Nullable
UserConnection getServerConnection(UUID uuid);
@Deprecated
@Nullable default UserConnection getConnectedClient(UUID uuid) {
return getServerConnection(uuid);
}
@Nullable UserConnection getConnectedClient(UUID clientIdentifier);
/**
* Returns the client UserConnection. See above for the connection types.
* Returns the UUID from the frontend connection to this proxy server
* Returns null when there isn't a server or this connection isn't frontend, or it doesn't have an id
* When ViaVersion is reloaded, this method may not return some players.
* <p>
* Note that connections are removed as soon as their channel is closed,
* so avoid using this method during player quits for example.
*
* @return client UserConnection of the player or null
* @return UUID of the frontend connection to this proxy server
*/
@Nullable
UserConnection getClientConnection(UUID uuid);
/**
* Returns a map containing the UUIDs and server UserConnections
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and frontend UserConnections
*/
Map<UUID, UserConnection> getServerConnections();
@Deprecated
default Map<UUID, UserConnection> getConnectedClients() {
return getServerConnections();
}
/**
* Returns a map containing the UUIDs and client UserConnections
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and client UserConnections
*/
Map<UUID, UserConnection> getClientConnections();
@Nullable UUID getConnectedClientId(UserConnection connection);
/**
* Returns all UserConnections which are registered
@@ -114,6 +84,15 @@ public interface ConnectionManager {
*/
Set<UserConnection> getConnections();
/**
* Returns a map containing the UUIDs and frontend UserConnections from players connected to this proxy server
* Returns empty list when there isn't a server
* When ViaVersion is reloaded, this method may not return some players.
*
* @return map containing the UUIDs and frontend UserConnections from players connected to this proxy server
*/
Map<UUID, UserConnection> getConnectedClients();
void onLoginSuccess(UserConnection connection);
void onDisconnect(UserConnection connection);
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -134,15 +134,6 @@ public interface ProtocolInfo {
void setUuid(UUID uuid);
/**
* Returns whether compression is enabled for this connection.
*
* @return whether compression is enabled
*/
boolean compressionEnabled();
void setCompressionEnabled(boolean compressionEnabled);
/**
* Returns the user's pipeline.
*
@@ -151,4 +142,4 @@ public interface ProtocolInfo {
ProtocolPipeline getPipeline();
void setPipeline(ProtocolPipeline pipeline);
}
}
@@ -1,45 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.connection;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
/**
* Holds protocol-specific data. Protocols may extend the data wrapper to hold extra data.
*/
public interface ProtocolStorables {
EntityTracker entityTracker();
void setEntityTracker(EntityTracker tracker);
ClientWorld clientWorld();
void setClientWorld(ClientWorld clientWorld);
ItemHasher itemHasher();
void setItemHasher(ItemHasher itemHasher);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,6 +30,15 @@ package com.viaversion.viaversion.api.connection;
*/
public interface StorableObject {
/**
* Returns whether the object should be uncached on a server switch.
*
* @return whether the object should be uncached on a server switch
*/
default boolean clearOnServerSwitch() {
return true;
}
default void onRemove() {
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -29,11 +29,6 @@ public abstract class StoredObject implements StorableObject {
this.user = user;
}
public UserConnection user() {
return this.user;
}
@Deprecated
public UserConnection getUser() {
return user;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,12 +22,8 @@
*/
package com.viaversion.viaversion.api.connection;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
import com.viaversion.viaversion.api.data.entity.EntityTracker;
import com.viaversion.viaversion.api.data.item.ItemHasher;
import com.viaversion.viaversion.api.minecraft.ClientWorld;
import com.viaversion.viaversion.api.protocol.Protocol;
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
@@ -38,18 +34,18 @@ import io.netty.channel.ChannelFuture;
import io.netty.handler.codec.CodecException;
import java.util.Collection;
import java.util.Map;
import java.util.UUID;
import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface UserConnection {
/**
* Get an object from the storage. Useful where protocol instances aren't readily available.
* Get an object from the storage.
*
* @param objectClass The class of the object to get
* @param <T> The type of the class you want to get.
* @return The requested object
* @see #storables(Protocol)
*/
@Nullable <T extends StorableObject> T get(Class<T> objectClass);
@@ -71,56 +67,27 @@ public interface UserConnection {
@Nullable <T extends StorableObject> T remove(Class<T> objectClass);
/**
* Put an object into the stored objects based on class. Useful where protocol instances aren't readily available.
* Put an object into the stored objects based on class.
*
* @param object The object to store.
* @see #storables(Protocol)
*/
void put(StorableObject object);
/**
* Holds protocol-specific data. Where protocol instances aren't readily available, use {@link #put(StorableObject)}.
*
* @param protocol protocol
* @param <T> protocol-specific storables type
* @return protocol storables
* @throws IllegalArgumentException if the protocol does not have a valid return value for {@link Protocol#index()}
*/
<T extends ProtocolStorables> T storables(Protocol<?, ?, ?, ?> protocol);
/**
* Holds protocol-specific data. Prefer using {@link #storables(Protocol)} where possible.
*
* @param protocolClass protocol class
* @param <T> protocol-specific storables type
* @return protocol storables
* @throws IllegalArgumentException if the protocol does not have a valid return value for {@link Protocol#index()}
* @see #storables(Protocol)
*/
default <T extends ProtocolStorables> T storables(final Class<? extends Protocol> protocolClass) {
return storables(Via.getManager().getProtocolManager().getProtocol(protocolClass));
}
/**
* Returns a collection of entity trackers currently registered.
*
* @return collection of entity trackers currently registered
*/
@Deprecated(forRemoval = true)
Collection<EntityTracker> getEntityTrackers();
@Deprecated(forRemoval = true)
@Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass);
/**
* Returns the entity tracker by the given protocol class if present.
*
* @param protocol protocol
* @param <T> entity tracker type
* @param protocolClass protocol class
* @param <T> entity tracker type
* @return entity tracker if present
* @see com.viaversion.viaversion.api.rewriter.EntityRewriter#tracker(UserConnection)
*/
@Nullable <T extends EntityTracker> T getEntityTracker(Protocol<?, ?, ?, ?> protocol);
@Nullable <T extends EntityTracker> T getEntityTracker(Class<? extends Protocol> protocolClass);
/**
* Adds an entity tracker to the user connection.
@@ -128,59 +95,23 @@ public interface UserConnection {
*
* @param protocolClass protocol class
* @param tracker entity tracker
* @deprecated use {@link #storables(Protocol)}
*/
@Deprecated(forRemoval = true)
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
/**
* Returns the item hasher by the given class if present.
*
* @param protocol protocol
* @param <T> item hasher type
* @return item hasher if present
* Clear stored objects and entity trackers.
*/
@Nullable <T extends ItemHasher> T getItemHasher(Protocol<?, ?, ?, ?> protocol);
default void clearStoredObjects() {
clearStoredObjects(false);
}
/**
* Adds an item hasher to the user connection.
* Clear stored objects and entity trackers.
* If cleared for a proxy server switch, some stored objects and tracker data will be retained.
*
* @param protocolClass protocol class
* @param itemHasher item hasher
* @deprecated use {@link #storables(Protocol)}
* @param isServerSwitch whether the clear is due to a server switch
*/
@Deprecated(forRemoval = true)
void addItemHasher(Class<? extends Protocol> protocolClass, ItemHasher itemHasher);
@Deprecated(forRemoval = true)
@Nullable <T extends ItemHasher> T getItemHasher(Class<? extends Protocol> protocolClass);
/**
* Returns the client world by the given class if present.
*
* @param protocolClass protocol class
* @param <T> client world type
* @return client world if present
* @deprecated use {@link #storables(Protocol)}
*/
@Nullable
@Deprecated(forRemoval = true)
<T extends ClientWorld> T getClientWorld(Class<? extends Protocol> protocolClass);
/**
* Adds a client world to the user connection.
* Does not override existing client worlds.
*
* @param protocolClass protocol class
* @param clientWorld client world
*/
@Deprecated(forRemoval = true)
void addClientWorld(Class<? extends Protocol> protocolClass, ClientWorld clientWorld);
/**
* Clear stored objects, entity trackers and client worlds.
*/
void clearStoredObjects();
void clearStoredObjects(boolean isServerSwitch);
/**
* Sends a raw packet to the connection on the current thread.
@@ -235,15 +166,9 @@ public interface UserConnection {
/**
* Monitors serverbound packets and returns whether a packet can/should be processed.
*
* @param bytes the number of bytes in the packet
* @return false if this packet should be cancelled
*/
boolean checkServerboundPacket(int bytes);
@Deprecated(forRemoval = true)
default boolean checkServerboundPacket() {
return checkServerboundPacket(0);
}
boolean checkServerboundPacket();
/**
* Monitors clientbound packets and returns whether a packet can/should be processed.
@@ -256,11 +181,6 @@ public interface UserConnection {
* @see #checkClientboundPacket()
* @see #checkServerboundPacket()
*/
default boolean checkIncomingPacket(final int bytes) {
return isClientSide() ? checkClientboundPacket() : checkServerboundPacket(bytes);
}
@Deprecated(forRemoval = true)
default boolean checkIncomingPacket() {
return isClientSide() ? checkClientboundPacket() : checkServerboundPacket();
}
@@ -379,37 +299,25 @@ public interface UserConnection {
void setPendingDisconnect(boolean pendingDisconnect);
/**
* Returns whether this is a backend connection.
* This is a mod integrated into the client, or for example a backend Velocity connection.
* Returns whether this is a client-side connection.
* This is a mod integrated into the client itself, or for example a backend Velocity connection.
*
* @return whether this is a backend connection
* @return whether this is a client-side connection
*/
boolean isClientSide();
/**
* Returns whether this is a frontend connection.
* This is a plugin integrated into the server, or for example a frontend Velocity connection.
*
* @return whether this is a frontend connection
*/
default boolean isServerSide() {
return !isClientSide();
}
/**
* Returns whether {@link ViaVersionConfig#blockedProtocolVersions()} should be checked for this connection.
*
* @return whether blocked protocols should be applied
*/
default boolean shouldApplyBlockProtocol() {
return isServerSide();
}
boolean shouldApplyBlockProtocol();
/**
* Returns a newly generated token that will let a packet be passed through without
* transforming its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
* Returns a newly generated uuid that will let a packet be passed through without
* transformig its contents if used together with {@link PacketWrapper#PASSTHROUGH_ID}.
*
* @return generated passthrough token
*/
long generatePassthroughToken();
UUID generatePassthroughToken();
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,64 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import com.viaversion.viaversion.util.Key;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import org.checkerframework.checker.nullness.qual.Nullable;
public class FullIdentityMappings extends FullMappingsBase {
public FullIdentityMappings(final IdentifiersPair identifiersPair, final Mappings mappings) {
this(toInverseMap(identifiersPair.unmapped()), identifiersPair.unmapped().stream().map(Key::of).toArray(Key[]::new), mappings);
}
private FullIdentityMappings(final Object2IntMap<String> stringToId, final Key[] idToKey, final Mappings mappings) {
super(stringToId, stringToId, idToKey, idToKey, mappings);
}
@Override
public @Nullable String identifier(final String mappedIdentifier) {
return mappedIdentifier(mappedIdentifier);
}
@Override
public @Nullable Key keyFromMappedKey(final String mappedIdentifier) {
return mappedKeyFromKey(mappedIdentifier);
}
@Override
public boolean isIdentity() {
return true;
}
@Override
public boolean isIntIdIdentity() {
return true;
}
@Override
public FullIdentityMappings inverse() {
return new FullIdentityMappings(stringToId, idToKey, mappings.inverse());
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,7 +22,6 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.viaversion.util.Key;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
@@ -52,21 +51,7 @@ public interface FullMappings extends BiMappings {
* @param id unmapped id
* @return unmapped string identifier, or null if out of bounds
*/
default @Nullable String identifier(int id) {
final Key key = keyFromId(id);
return key != null ? key.toString() : null;
}
/**
* Returns the unmapped string identifier for the given mapped identifier.
*
* @param mappedIdentifier mapped identifier
* @return unmapped string identifier, or null if not found
*/
default @Nullable String identifier(String mappedIdentifier) {
final Key key = keyFromMappedKey(mappedIdentifier);
return key != null ? key.toString() : null;
}
@Nullable String identifier(int id);
/**
* Returns the mapped string identifier for the given mapped id.
@@ -74,10 +59,7 @@ public interface FullMappings extends BiMappings {
* @param mappedId mapped id
* @return mapped string identifier, or null if out of bounds
*/
default @Nullable String mappedIdentifier(int mappedId) {
final Key key = mappedKeyFromMappedId(mappedId);
return key != null ? key.toString() : null;
}
@Nullable String mappedIdentifier(int mappedId);
/**
* Returns the mapped string identifier for the given unmapped identifier.
@@ -85,50 +67,7 @@ public interface FullMappings extends BiMappings {
* @param identifier unmapped identifier
* @return mapped string identifier, or null if not found
*/
default @Nullable String mappedIdentifier(String identifier) {
final Key key = mappedKeyFromKey(identifier);
return key != null ? key.toString() : null;
}
/**
* Returns the unmapped key for the given mapped id.
*
* @param id unmapped id
* @return unmapped key, or null if out of bounds
*/
@Nullable Key keyFromId(int id);
/**
* Returns the unmapped key for the given mapped identifier.
*
* @param mappedIdentifier mapped identifier
* @return unmapped key, or null if not found
*/
@Nullable Key keyFromMappedKey(String mappedIdentifier);
/**
* Returns the mapped key for the given mapped id.
*
* @param mappedId mapped id
* @return mapped key, or null if out of bounds
*/
@Nullable Key mappedKeyFromMappedId(int mappedId);
/**
* Returns the mapped key for the given unmapped identifier.
*
* @param identifier unmapped identifier
* @return mapped key, or null if not found
*/
@Nullable Key mappedKeyFromKey(String identifier);
/**
* Returns whether the int id mappings are identity mappings.
*
* @return whether the int id mappings are identity mappings
* @see #isIdentity()
*/
boolean isIntIdIdentity();
@Nullable String mappedIdentifier(String identifier);
@Override
FullMappings inverse();
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,7 +23,6 @@
package com.viaversion.viaversion.api.data;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import com.viaversion.viaversion.util.Key;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
@@ -31,34 +30,31 @@ import java.util.List;
import org.checkerframework.checker.nullness.qual.Nullable;
public class FullMappingsBase implements FullMappings {
protected final Object2IntMap<String> stringToId;
protected final Object2IntMap<String> mappedStringToId;
protected final Key[] idToKey;
protected final Key[] mappedIdToKey;
protected final Mappings mappings;
private static final String[] EMPTY_ARRAY = new String[0];
private final Object2IntMap<String> stringToId;
private final Object2IntMap<String> mappedStringToId;
private final String[] idToString;
private final String[] mappedIdToString;
private final Mappings mappings;
public FullMappingsBase(final IdentifiersPair identifiersPair, final Mappings mappings) {
public FullMappingsBase(final List<String> unmappedIdentifiers, final List<String> mappedIdentifiers, final Mappings mappings) {
Preconditions.checkNotNull(mappings, "Mappings cannot be null");
this.mappings = mappings;
this.stringToId = toInverseMap(identifiersPair.unmapped());
this.idToKey = identifiersPair.unmapped().stream().map(Key::of).toArray(Key[]::new);
this.mappedStringToId = toInverseMap(identifiersPair.mapped());
this.mappedIdToKey = identifiersPair.mapped().stream().map(Key::of).toArray(Key[]::new);
this.stringToId = toInverseMap(unmappedIdentifiers);
this.mappedStringToId = toInverseMap(mappedIdentifiers);
this.idToString = unmappedIdentifiers.toArray(EMPTY_ARRAY);
this.mappedIdToString = mappedIdentifiers.toArray(EMPTY_ARRAY);
}
protected FullMappingsBase(final Object2IntMap<String> stringToId, final Object2IntMap<String> mappedStringToId, final Key[] idToKey, final Key[] mappedIdToKey, final Mappings mappings) {
private FullMappingsBase(final Object2IntMap<String> stringToId, final Object2IntMap<String> mappedStringToId, final String[] idToString, final String[] mappedIdToString, final Mappings mappings) {
this.stringToId = stringToId;
this.mappedStringToId = mappedStringToId;
this.idToKey = idToKey;
this.mappedIdToKey = mappedIdToKey;
this.idToString = idToString;
this.mappedIdToString = mappedIdToString;
this.mappings = mappings;
}
public static FullMappings of(final IdentifiersPair identifiersPair, final Mappings mappings) {
return mappings.isIdentity() && identifiersPair.identity() ? new FullIdentityMappings(identifiersPair, mappings) : new FullMappingsBase(identifiersPair, mappings);
}
static Object2IntMap<String> toInverseMap(final List<String> list) {
private static Object2IntMap<String> toInverseMap(final List<String> list) {
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(list.size());
map.defaultReturnValue(-1);
for (int i = 0; i < list.size(); i++) {
@@ -78,43 +74,34 @@ public class FullMappingsBase implements FullMappings {
}
@Override
public @Nullable Key keyFromId(final int id) {
if (id < 0 || id >= idToKey.length) {
public String identifier(final int id) {
if (id < 0 || id >= idToString.length) {
return null;
}
return idToKey[id];
final String identifier = idToString[id];
return Key.namespaced(identifier);
}
@Override
public @Nullable Key keyFromMappedKey(final String mappedIdentifier) {
final int mappedId = mappedId(mappedIdentifier);
if (mappedId == -1) {
public String mappedIdentifier(final int mappedId) {
if (mappedId < 0 || mappedId >= mappedIdToString.length) {
return null;
}
final int id = mappings.inverse().getNewId(mappedId);
return id != -1 ? keyFromId(id) : null;
final String identifier = mappedIdToString[mappedId];
return Key.namespaced(identifier);
}
@Override
public @Nullable Key mappedKeyFromMappedId(final int mappedId) {
if (mappedId < 0 || mappedId >= mappedIdToKey.length) {
return null;
}
return mappedIdToKey[mappedId];
}
@Override
public @Nullable Key mappedKeyFromKey(final String identifier) {
public @Nullable String mappedIdentifier(final String identifier) {
final int id = id(identifier);
if (id == -1) {
return null;
}
final int mappedId = mappings.getNewId(id);
return mappedId != -1 ? mappedKeyFromMappedId(mappedId) : null;
return mappedId != -1 ? mappedIdentifier(mappedId) : null;
}
@Override
@@ -137,13 +124,8 @@ public class FullMappingsBase implements FullMappings {
return mappings.mappedSize();
}
@Override
public boolean isIntIdIdentity() {
return mappings.isIdentity();
}
@Override
public FullMappings inverse() {
return new FullMappingsBase(mappedStringToId, stringToId, mappedIdToKey, idToKey, mappings.inverse());
return new FullMappingsBase(mappedStringToId, stringToId, mappedIdToString, idToString, mappings.inverse());
}
}
@@ -1,72 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.function.IntConsumer;
/**
* Reads sets of non-negative ints stored as ranges, packed into a byte array of varints.
* Each range is stored as an offset and length pair. The offset is the start of the first range and the
* difference to the previous range's exclusive end; the length is the inclusive end minus the start.
*/
public final class IdRanges {
/**
* Returns the encoded id set as an int set.
*
* @param rangesTag tag with the encoded ranges
* @return decoded ids
*/
public static IntSet decode(final ByteArrayTag rangesTag) {
final IntSet ids = new IntOpenHashSet();
forEachId(rangesTag, ids::add);
return ids;
}
public static IntList decodeAsList(final ByteArrayTag rangesTag) {
final IntList ids = new IntArrayList();
forEachId(rangesTag, ids::add);
return ids;
}
public static void forEachId(final ByteArrayTag rangesTag, final IntConsumer consumer) {
final ByteBuf buf = Unpooled.wrappedBuffer(rangesTag.getValue());
int prevEnd = 0;
while (buf.isReadable()) {
final int start = prevEnd + Types.VAR_INT.readPrimitive(buf);
final int end = start + Types.VAR_INT.readPrimitive(buf);
for (int id = start; id <= end; id++) {
consumer.accept(id);
}
prevEnd = end + 1;
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -38,9 +38,4 @@ public record IdentityMappings(int size, int mappedSize) implements Mappings {
public Mappings inverse() {
return new IdentityMappings(mappedSize, size);
}
@Override
public boolean isIdentity() {
return true;
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,111 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import com.viaversion.viaversion.util.Key;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Full mappings for versions where required identifiers hadn't yet followed the resource location format (i.e., pre-1.9.4 sounds).
*/
public class LegacyFullStringMappingsBase extends FullMappingsBase {
private final String[] idToString;
private final String[] mappedIdToString;
public LegacyFullStringMappingsBase(final IdentifiersPair identifiersPair, final Mappings mappings) {
super(toInverseMap(identifiersPair.unmapped()), toInverseMap(identifiersPair.mapped()), new Key[0], new Key[0], mappings);
this.idToString = identifiersPair.unmapped().toArray(new String[0]);
this.mappedIdToString = identifiersPair.mapped().toArray(new String[0]);
}
private LegacyFullStringMappingsBase(final Object2IntMap<String> stringToId, final Object2IntMap<String> mappedStringToId, final String[] idToKey, final String[] mappedIdToString, final Mappings mappings) {
super(stringToId, mappedStringToId, new Key[0], new Key[0], mappings);
this.idToString = idToKey;
this.mappedIdToString = mappedIdToString;
}
@Override
public String identifier(final int id) {
if (id < 0 || id >= idToString.length) {
return null;
}
return Key.namespaced(idToString[id]);
}
@Override
public @Nullable String identifier(final String mappedIdentifier) {
final int mappedId = mappedId(mappedIdentifier);
if (mappedId == -1) {
return null;
}
final int id = mappings.inverse().getNewId(mappedId);
return id != -1 ? identifier(id) : null;
}
@Override
public @Nullable String mappedIdentifier(final int mappedId) {
if (mappedId < 0 || mappedId >= mappedIdToString.length) {
return null;
}
return Key.namespaced(mappedIdToString[mappedId]);
}
@Override
public @Nullable String mappedIdentifier(final String identifier) {
final int id = id(identifier);
if (id == -1) {
return null;
}
final int mappedId = mappings.getNewId(id);
return mappedId != -1 ? mappedIdentifier(mappedId) : null;
}
@Override
public @Nullable Key keyFromId(final int id) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Key keyFromMappedKey(final String mappedIdentifier) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Key mappedKeyFromMappedId(final int mappedId) {
throw new UnsupportedOperationException();
}
@Override
public @Nullable Key mappedKeyFromKey(final String identifier) {
throw new UnsupportedOperationException();
}
@Override
public FullMappings inverse() {
return new LegacyFullStringMappingsBase(mappedStringToId, stringToId, mappedIdToString, idToString, mappings.inverse());
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,14 +22,9 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.viaversion.api.minecraft.RegistryKey;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.TagData;
import com.viaversion.viaversion.util.Key;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface MappingData {
@@ -40,84 +35,52 @@ public interface MappingData {
void load();
/**
* Returns the mapped block state id, or 0 if unmapped.
* Returns the mapped block state id, or -1 if unmapped.
*
* @param id unmapped block state id
* @return mapped block state id, or 0 if unmapped
* @return mapped block state id, or -1 if unmapped
* @throws NullPointerException if this mappingdata does not hold block state mappings
*/
int getNewBlockStateId(int id);
/**
* Returns the mapped block id, or 0 if unmapped.
* Returns the mapped block id, or -1 if unmapped.
*
* @param id unmapped block id
* @return mapped block id, or 0 if unmapped
* @return mapped block id, or -1 if unmapped
* @throws NullPointerException if this mappingdata does not hold block mappings
*/
int getNewBlockId(int id);
/**
* Returns the backwards mapped block id, or 1 if unmapped.
*
* @param id mapped block id
* @return backwards mapped block id, or 1 if unmapped
*/
int getOldBlockId(int id);
/**
* Returns the mapped item id, or 0 if unmapped.
* Returns the mapped item id, or -1 if unmapped.
*
* @param id unmapped item id
* @return mapped item id, or 0 if unmapped
* @return mapped item id, or -1 if unmapped
* @throws NullPointerException if this mappingdata does not hold item mappings
*/
int getNewItemId(int id);
/**
* Returns the backwards mapped item id, or 1 if unmapped.
* Returns the backwards mapped item id, or -1 if unmapped.
*
* @param id mapped item id
* @return backwards mapped item id, or 1 if unmapped
* @return backwards mapped item id, or -1 if unmapped
* @throws NullPointerException if this mappingdata does not hold item mappings
*/
int getOldItemId(int id);
/**
* Returns the mapped particle id, or 0 if unmapped.
* Returns the mapped particle id, or -1 if unmapped.
*
* @param id unmapped particle id
* @return mapped particle id, or 0 if unmapped
* @return mapped particle id, or -1 if unmapped
* @throws NullPointerException if this mappingdata does not hold particle mappings
*/
int getNewParticleId(int id);
/**
* Returns the mapped attribute id, or 0 if unmapped.
*
* @param id unmapped attribute id
* @return mapped attribute id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold attribute mappings
*/
int getNewAttributeId(int id);
/**
* Returns the mapped sound id, or 0 if unmapped.
*
* @param id unmapped sound id
* @return mapped sound id, or 0 if unmapped
* @throws NullPointerException if this mappingdata does not hold sound mappings
*/
int getNewSoundId(int id);
/**
* Returns the backwards mapped sound id, or 1 if unmapped.
*
* @param i mapped sound id
* @return backwards mapped sound id, or 1 if unmapped
*/
int getOldSoundId(int i);
/**
* Returns a list of tags to send if present.
*
@@ -145,73 +108,27 @@ public interface MappingData {
@Nullable Mappings getBlockMappings();
@Nullable FullMappings getFullBlockMappings();
@Nullable Mappings getBlockEntityMappings();
@Nullable Mappings getBlockStateMappings();
@Nullable Mappings getSoundMappings();
@Nullable FullMappings getFullSoundMappings();
@Nullable Mappings getStatisticsMappings();
@Nullable Mappings getMenuMappings();
@Nullable Mappings getEnchantmentMappings();
@Nullable Mappings getAttributeMappings();
@Nullable Mappings getPaintingMappings();
@Nullable FullMappings getBlockEntityMappings();
@Nullable FullMappings getAttributeMappings();
@Nullable FullMappings getEntityMappings();
@Nullable FullMappings getArgumentTypeMappings();
@Nullable FullMappings getRecipeSerializerMappings();
@Nullable FullMappings getSlotDisplayMappings();
@Nullable FullMappings getDataComponentSerializerMappings();
default @Nullable FullMappings getFullMappings(final MappingType mappingType) {
return switch (mappingType) {
case ITEM -> getFullItemMappings();
case BLOCK -> getFullBlockMappings();
case SOUND -> getFullSoundMappings();
case ENTITY_TYPE -> getEntityMappings();
};
}
/**
* Set of block (not block state) ids that had their base type or properties changed.
*
* @return set of changed block ids, or null if not tracked/none are present
*/
@Nullable IntSet changedBlocks();
default boolean hasBlockChanged(final int blockId) {
return changedBlocks() != null && changedBlocks().contains(blockId);
}
@Nullable Set<String> changedEnvironmentAttributes();
/**
* Type of mappings. Currently only relevant for ops writing of generic holder classes and expanded when needed.
*/
enum MappingType implements RegistryKey {
ITEM, BLOCK, SOUND, ENTITY_TYPE;
private final Key key;
MappingType() {
this.key = Key.of(name().toLowerCase(Locale.ROOT));
}
@Override
public Key registry() {
return this.key;
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,53 +22,39 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.nbt.tag.ByteArrayTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import com.viaversion.viaversion.api.minecraft.RegistryType;
import com.viaversion.viaversion.api.minecraft.TagData;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.checkerframework.checker.nullness.qual.Nullable;
public class MappingDataBase implements MappingData {
protected final String unmappedVersion;
protected final String mappedVersion;
protected BiMappings itemMappings;
protected FullMappings argumentTypeMappings;
protected FullMappings entityMappings;
protected FullMappings recipeSerializerMappings;
protected FullMappings itemDataSerializerMappings;
protected FullMappings slotDisplayMappings;
protected FullMappings attributeMappings;
protected FullMappings blockEntityMappings;
protected ParticleMappings particleMappings;
protected BiMappings itemMappings;
protected BiMappings blockMappings;
protected Mappings blockMappings;
protected Mappings blockStateMappings;
protected Mappings blockEntityMappings;
protected Mappings soundMappings;
protected Mappings statisticsMappings;
protected Mappings enchantmentMappings;
protected Mappings paintingMappings;
protected Mappings menuMappings;
protected Mappings attributeMappings;
protected Map<RegistryType, List<TagData>> tags;
/**
* Set of block ids that have had type or property changes.
*/
protected IntSet changedBlocks;
protected Set<String> changedEnvironmentAttributes;
public MappingDataBase(final String unmappedVersion, final String mappedVersion) {
this.unmappedVersion = unmappedVersion;
@@ -82,40 +68,38 @@ public class MappingDataBase implements MappingData {
}
final CompoundTag data = readMappingsFile("mappings-" + unmappedVersion + "to" + mappedVersion + ".nbt");
blockMappings = loadMappings(data, "blocks");
blockStateMappings = loadMappings(data, "blockstates");
blockEntityMappings = loadMappings(data, "blockentities");
soundMappings = loadMappings(data, "sounds");
statisticsMappings = loadMappings(data, "statistics");
menuMappings = loadMappings(data, "menus");
enchantmentMappings = loadMappings(data, "enchantments");
paintingMappings = loadMappings(data, "paintings");
attributeMappings = loadMappings(data, "attributes");
final CompoundTag unmappedIdentifierData = readUnmappedIdentifiersFile("identifiers-" + unmappedVersion + ".nbt");
final CompoundTag mappedIdentifierData = readMappedIdentifiersFile("identifiers-" + mappedVersion + ".nbt");
if (unmappedIdentifierData != null && mappedIdentifierData != null) {
itemMappings = loadFullOrBiMappings(data, unmappedIdentifierData, mappedIdentifierData, "items");
blockMappings = loadFullOrBiMappings(data, unmappedIdentifierData, mappedIdentifierData, "blocks");
soundMappings = loadFullOrBiMappings(data, unmappedIdentifierData, mappedIdentifierData, "sounds");
itemMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "items");
entityMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "entities");
argumentTypeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "argumenttypes");
slotDisplayMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "slot_displays");
recipeSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "recipe_serializers");
itemDataSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "data_component_type");
attributeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "attributes");
blockEntityMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "blockentities");
final IdentifiersPair particleIdentifiers = identifiersFromGlobalIds(unmappedIdentifierData, mappedIdentifierData, "particles");
if (particleIdentifiers != null) {
final List<String> unmappedParticles = identifiersFromGlobalIds(unmappedIdentifierData, "particles");
final List<String> mappedParticles = identifiersFromGlobalIds(mappedIdentifierData, "particles");
if (unmappedParticles != null && mappedParticles != null) {
Mappings particleMappings = loadMappings(data, "particles");
if (particleMappings == null) {
particleMappings = new IdentityMappings(particleIdentifiers.unmapped().size(), particleIdentifiers.mapped().size());
particleMappings = new IdentityMappings(unmappedParticles.size(), mappedParticles.size());
}
this.particleMappings = new ParticleMappings(particleIdentifiers, particleMappings);
this.particleMappings = new ParticleMappings(unmappedParticles, mappedParticles, particleMappings);
}
} else {
// Might not have identifiers in older versions
itemMappings = loadBiMappings(data, "items");
blockMappings = loadBiMappings(data, "blocks");
soundMappings = loadMappings(data, "sounds");
}
final CompoundTag tagsTag = data.getCompoundTag("tags");
@@ -124,17 +108,6 @@ public class MappingDataBase implements MappingData {
loadTags(RegistryType.ITEM, tagsTag);
loadTags(RegistryType.BLOCK, tagsTag);
loadTags(RegistryType.ENTITY, tagsTag);
loadTags(RegistryType.FLUID, tagsTag);
}
final IntArrayTag changedBlocks = data.getIntArrayTag("changed_blocks");
if (changedBlocks != null) {
this.changedBlocks = new IntOpenHashSet(changedBlocks.getValue());
}
final ListTag<StringTag> changedEnvironmentAttributes = data.getListTag("changed_environment_attributes", StringTag.class);
if (changedEnvironmentAttributes != null) {
this.changedEnvironmentAttributes = changedEnvironmentAttributes.stream().map(StringTag::getValue).collect(Collectors.toSet());
}
loadExtras(data);
@@ -144,10 +117,6 @@ public class MappingDataBase implements MappingData {
return MappingDataLoader.INSTANCE.identifiersFromGlobalIds(mappingsTag, key);
}
protected @Nullable IdentifiersPair identifiersFromGlobalIds(final CompoundTag unmappedTag, final CompoundTag mappedTag, final String key) {
return MappingDataLoader.INSTANCE.identifiersFromGlobalIds(unmappedTag, mappedTag, key);
}
protected @Nullable CompoundTag readMappingsFile(final String name) {
return MappingDataLoader.INSTANCE.loadNBT(name);
}
@@ -164,26 +133,19 @@ public class MappingDataBase implements MappingData {
return MappingDataLoader.INSTANCE.loadMappings(data, key);
}
protected @Nullable BiMappings loadFullOrBiMappings(final CompoundTag data, final CompoundTag unmappedIdentifiersTag, final CompoundTag mappedIdentifiersTag, final String key) {
final FullMappings mappings = loadFullMappings(data, unmappedIdentifiersTag, mappedIdentifiersTag, key);
return mappings != null ? mappings : loadBiMappings(data, key);
}
protected @Nullable FullMappings loadFullMappings(final CompoundTag data, final CompoundTag unmappedIdentifiersTag, final CompoundTag mappedIdentifiersTag, final String key) {
if (!unmappedIdentifiersTag.contains(key) || !mappedIdentifiersTag.contains(key)) {
return null;
}
final IdentifiersPair identifiersPair = identifiersFromGlobalIds(unmappedIdentifiersTag, mappedIdentifiersTag, key);
final List<String> unmappedIdentifiers = identifiersFromGlobalIds(unmappedIdentifiersTag, key);
final List<String> mappedIdentifiers = identifiersFromGlobalIds(mappedIdentifiersTag, key);
Mappings mappings = loadBiMappings(data, key); // Load as bi-mappings to keep the inverse cached
if (mappings == null) {
mappings = new IdentityMappings(identifiersPair.unmapped().size(), identifiersPair.mapped().size());
mappings = new IdentityMappings(unmappedIdentifiers.size(), mappedIdentifiers.size());
}
return createFullMappings(identifiersPair, mappings);
}
protected FullMappings createFullMappings(final IdentifiersPair identifiersPair, final Mappings mappings) {
return FullMappingsBase.of(identifiersPair, mappings);
return new FullMappingsBase(unmappedIdentifiers, mappedIdentifiers, mappings);
}
protected @Nullable BiMappings loadBiMappings(final CompoundTag data, final String key) {
@@ -192,21 +154,15 @@ public class MappingDataBase implements MappingData {
}
private void loadTags(final RegistryType type, final CompoundTag data) {
final CompoundTag tag = data.getCompoundTag(type.identifier());
final CompoundTag tag = data.getCompoundTag(type.resourceLocation());
if (tag == null) {
return;
}
final List<TagData> tagsList = new ArrayList<>(tags.size());
for (final Map.Entry<String, Tag> entry : tag.entrySet()) {
final int[] entries;
if (entry.getValue() instanceof final ByteArrayTag rangesTag) {
entries = IdRanges.decodeAsList(rangesTag).toIntArray();
} else {
// Old format / if the values need to be sorted
entries = ((IntArrayTag) entry.getValue()).getValue();
}
tagsList.add(new TagData(entry.getKey(), entries));
final IntArrayTag entries = (IntArrayTag) entry.getValue();
tagsList.add(new TagData(entry.getKey(), entries.getValue()));
}
this.tags.put(type, tagsList);
@@ -222,11 +178,6 @@ public class MappingDataBase implements MappingData {
return checkValidity(id, blockMappings.getNewId(id), "block");
}
@Override
public int getOldBlockId(final int id) {
return blockMappings.inverse().getNewIdOrDefault(id, 1);
}
@Override
public int getNewItemId(final int id) {
return checkValidity(id, itemMappings.getNewId(id), "item");
@@ -247,16 +198,6 @@ public class MappingDataBase implements MappingData {
return checkValidity(id, attributeMappings.getNewId(id), "attributes");
}
@Override
public int getNewSoundId(final int id) {
return checkValidity(id, soundMappings.getNewId(id), "sound");
}
@Override
public int getOldSoundId(final int id) {
return soundMappings.inverse().getNewIdOrDefault(id, 0);
}
@Override
public @Nullable List<TagData> getTags(final RegistryType type) {
return tags != null ? tags.get(type) : null;
@@ -269,8 +210,8 @@ public class MappingDataBase implements MappingData {
@Override
public @Nullable FullMappings getFullItemMappings() {
if (itemMappings instanceof FullMappings fullItemMappings) {
return fullItemMappings;
if (itemMappings instanceof FullMappings) {
return (FullMappings) itemMappings;
}
return null;
}
@@ -286,15 +227,7 @@ public class MappingDataBase implements MappingData {
}
@Override
public @Nullable FullMappings getFullBlockMappings() {
if (blockMappings instanceof FullMappings fullBlockMappings) {
return fullBlockMappings;
}
return null;
}
@Override
public @Nullable FullMappings getBlockEntityMappings() {
public @Nullable Mappings getBlockEntityMappings() {
return blockEntityMappings;
}
@@ -308,14 +241,6 @@ public class MappingDataBase implements MappingData {
return soundMappings;
}
@Override
public @Nullable FullMappings getFullSoundMappings() {
if (soundMappings instanceof FullMappings fullSoundMappings) {
return fullSoundMappings;
}
return null;
}
@Override
public @Nullable Mappings getStatisticsMappings() {
return statisticsMappings;
@@ -332,7 +257,7 @@ public class MappingDataBase implements MappingData {
}
@Override
public @Nullable FullMappings getAttributeMappings() {
public @Nullable Mappings getAttributeMappings() {
return attributeMappings;
}
@@ -361,21 +286,6 @@ public class MappingDataBase implements MappingData {
return recipeSerializerMappings;
}
@Override
public @Nullable FullMappings getSlotDisplayMappings() {
return slotDisplayMappings;
}
@Override
public @Nullable IntSet changedBlocks() {
return changedBlocks;
}
@Override
public @Nullable Set<String> changedEnvironmentAttributes() {
return changedEnvironmentAttributes;
}
protected Logger getLogger() {
return Via.getPlatform().getLogger();
}
@@ -390,7 +300,7 @@ public class MappingDataBase implements MappingData {
*/
protected int checkValidity(final int id, final int mappedId, final String type) {
if (mappedId == -1) {
if (Via.getConfig().logOtherConversionWarnings()) {
if (!Via.getConfig().isSuppressConversionWarnings()) {
getLogger().warning(String.format("Missing %s %s for %s %s %d", mappedVersion, type, unmappedVersion, type, id));
}
return 0;
@@ -400,4 +310,4 @@ public class MappingDataBase implements MappingData {
protected void loadExtras(final CompoundTag data) {
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -30,18 +30,15 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonSyntaxException;
import com.viaversion.nbt.io.NBTIO;
import com.viaversion.nbt.io.TagReader;
import com.viaversion.nbt.tag.ByteTag;
import com.viaversion.nbt.tag.CompoundTag;
import com.viaversion.nbt.tag.IntArrayTag;
import com.viaversion.nbt.tag.IntTag;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.GsonUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.io.BufferedInputStream;
@@ -55,7 +52,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -64,16 +60,15 @@ public class MappingDataLoader {
public static final MappingDataLoader INSTANCE = new MappingDataLoader(MappingDataLoader.class, "assets/viaversion/data/");
public static final TagReader<CompoundTag> MAPPINGS_READER = NBTIO.reader(CompoundTag.class).named();
private static final Map<String, String[]> GLOBAL_IDENTIFIER_INDEXES = new HashMap<>();
private static final int VERSION = 2;
private static final byte DIRECT_ID = 0;
private static final byte SHIFTS_ID = 1;
private static final byte CHANGES_ID = 2;
private static final byte IDENTITY_ID = 3;
private final Map<String, CompoundTag> mappingsCache = new ConcurrentHashMap<>();
private final Map<String, CompoundTag> mappingsCache = new HashMap<>();
private final Class<?> dataLoaderClass;
private final String dataPath;
private volatile boolean cacheValid = true;
private boolean cacheValid = true;
public MappingDataLoader(final Class<?> dataLoaderClass, final String dataPath) {
this.dataLoaderClass = dataLoaderClass;
@@ -87,9 +82,8 @@ public class MappingDataLoader {
for (final Map.Entry<String, Tag> entry : globalIdentifiers.entrySet()) {
//noinspection unchecked
final ListTag<StringTag> value = (ListTag<StringTag>) entry.getValue();
final int size = value.size();
final String[] array = new String[size];
for (int i = 0; i < size; i++) {
final String[] array = new String[value.size()];
for (int i = 0, size = value.size(); i < size; i++) {
array[i] = value.get(i).getValue();
}
GLOBAL_IDENTIFIER_INDEXES.put(entry.getKey(), array);
@@ -110,14 +104,14 @@ public class MappingDataLoader {
throw new IllegalArgumentException("Unknown global identifier key: " + registry);
}
if (globalId < 0 || globalId >= array.length) {
throw new IllegalArgumentException("Unknown global identifier index: " + registry + "/" + globalId);
throw new IllegalArgumentException("Unknown global identifier index: " + globalId);
}
return array[globalId];
}
public void clearCache() {
cacheValid = false;
mappingsCache.clear();
cacheValid = false;
}
/**
@@ -166,14 +160,17 @@ public class MappingDataLoader {
return loadNBTFromFile(name);
}
if (cache) {
// Also blocks concurrent loaders of the same file until the first one has finished
return mappingsCache.computeIfAbsent(name, this::loadNBTFromFile);
CompoundTag data = mappingsCache.get(name);
if (data != null) {
return data;
}
// Still do a lookup, but don't store it
final CompoundTag data = mappingsCache.get(name);
return data != null ? data : loadNBTFromFile(name);
data = loadNBTFromFile(name);
if (cache && data != null) {
mappingsCache.put(name, data);
}
return data;
}
public @Nullable CompoundTag loadNBT(final String name) {
@@ -214,180 +211,79 @@ public class MappingDataLoader {
return null;
}
final int version = mappingsTag.getInt("version", -1);
if (version != VERSION) {
throw new IllegalArgumentException("Invalid version: " + version);
}
final int mappedSize = tag.getInt("mappedSize", -1);
final byte strategy = tag.getByteTag("id").asByte();
final ByteTag serializationStragetyTag = tag.getUnchecked("id");
final IntTag mappedSizeTag = tag.getUnchecked("mappedSize");
final byte strategy = serializationStragetyTag.asByte();
final V mappings;
if (strategy == DIRECT_ID) {
// Zigzag varints of the difference to the previous mapped id
final int size = tag.getIntTag("size").asInt();
final ByteBuf buf = Unpooled.wrappedBuffer(tag.getByteArrayTag("val").getValue());
final int[] values = new int[size];
int prev = 0;
for (int i = 0; i < size; i++) {
prev += readZigZagVarInt(buf);
values[i] = prev;
}
return IntArrayMappings.of(values, mappedSize);
final IntArrayTag valuesTag = tag.getIntArrayTag("val");
return IntArrayMappings.of(valuesTag.getValue(), mappedSizeTag.asInt());
} else if (strategy == SHIFTS_ID) {
final ValuePairs pairs = readAtValuePairs(tag);
final int[] shiftsAt = pairs.first;
final int[] shiftsTo = pairs.second;
final int size = tag.getIntTag("size").asInt();
final IntArrayTag shiftsAtTag = tag.getIntArrayTag("at");
final IntArrayTag shiftsTag = tag.getIntArrayTag("to");
final IntTag sizeTag = tag.getUnchecked("size");
final int[] shiftsAt = shiftsAtTag.getValue();
final int[] shiftsTo = shiftsTag.getValue();
final int size = sizeTag.asInt();
mappings = holderSupplier.get(size);
// Handle values until first shift
if (shiftsAt[0] != 0) {
// Add identity values before the first shift
final int to = shiftsAt[0];
for (int id = 0; id < to; id++) {
addConsumer.addTo(mappings, id, id);
}
}
// Read shifts
// Handle shifts
for (int i = 0; i < shiftsAt.length; i++) {
final boolean isLast = i == shiftsAt.length - 1;
final int from = shiftsAt[i];
final int to = isLast ? size : shiftsAt[i + 1];
final int to = i == shiftsAt.length - 1 ? size : shiftsAt[i + 1];
int mappedId = shiftsTo[i];
for (int id = from; id < to; id++) {
addConsumer.addTo(mappings, id, mappedId++);
}
}
} else if (strategy == CHANGES_ID) {
final ValuePairs pairs = readAtValuePairs(tag);
final int[] changesAt = pairs.first;
final int[] values = pairs.second;
final int size = tag.getIntTag("size").asInt();
final IntArrayTag changesAtTag = tag.getIntArrayTag("at");
final IntArrayTag valuesTag = tag.getIntArrayTag("val");
final IntTag sizeTag = tag.getUnchecked("size");
final boolean fillBetween = tag.get("nofill") == null;
mappings = holderSupplier.get(size);
final int[] changesAt = changesAtTag.getValue();
final int[] values = valuesTag.getValue();
mappings = holderSupplier.get(sizeTag.asInt());
int nextUnhandledId = 0;
for (int i = 0; i < changesAt.length; i++) {
final int changedId = changesAt[i];
final int id = changesAt[i];
if (fillBetween) {
// Fill from after the last change to before this change with unchanged ids
for (int id = nextUnhandledId; id < changedId; id++) {
addConsumer.addTo(mappings, id, id);
final int previousId = i != 0 ? changesAt[i - 1] + 1 : 0;
for (int identity = previousId; identity < id; identity++) {
addConsumer.addTo(mappings, identity, identity);
}
nextUnhandledId = changedId + 1;
}
// Assign the changed value
addConsumer.addTo(mappings, changedId, values[i]);
}
// Fill the remainder
if (fillBetween && nextUnhandledId != size) {
for (int id = nextUnhandledId; id < size; id++) {
addConsumer.addTo(mappings, id, id);
}
addConsumer.addTo(mappings, id, values[i]);
}
} else if (strategy == IDENTITY_ID) {
final IntTag sizeTag = tag.getIntTag("size");
return new IdentityMappings(sizeTag.asInt(), mappedSize);
final IntTag sizeTag = tag.getUnchecked("size");
return new IdentityMappings(sizeTag.asInt(), mappedSizeTag.asInt());
} else {
throw new IllegalArgumentException("Unknown serialization strategy: " + strategy);
}
return mappingsSupplier.create(mappings, mappedSize);
}
/**
* Reads alternating id and value pairs from varints. The id as the difference to the previous id,
* the value as the zigzag difference to the previous value.
*
* @param tag tag to read the packed values from
* @return array of ids and array of values
*/
private static ValuePairs readAtValuePairs(final CompoundTag tag) {
final ByteBuf buf = Unpooled.wrappedBuffer(tag.getByteArrayTag("val").getValue());
final IntList at = new IntArrayList();
final IntList values = new IntArrayList();
int prevAt = -1;
int prevValue = 0;
while (buf.isReadable()) {
prevAt = prevAt + 1 + Types.VAR_INT.readPrimitive(buf);
prevValue += readZigZagVarInt(buf);
at.add(prevAt);
values.add(prevValue);
}
return new ValuePairs(at.toIntArray(), values.toIntArray());
}
private static int readZigZagVarInt(final ByteBuf buf) {
// https://lemire.me/blog/2022/11/25/making-all-your-integers-positive-with-zigzag-encoding/
// In short, using deltas to previous ids makes the numbers small, and using zigzag encoding means they're all positive.
// Being all positive means we can use varints to make most of the data much shorter than 8 bytes.
// All of that combined ends up having a decent effect when compressed in the jar file as well.
final int value = Types.VAR_INT.readPrimitive(buf);
return (value >>> 1) ^ -(value & 1);
return mappingsSupplier.create(mappings, mappedSizeTag.asInt());
}
public @Nullable List<String> identifiersFromGlobalIds(final CompoundTag mappingsTag, final String key) {
final Mappings mappings = loadMappings(mappingsTag, key);
return mappings != null ? identifiers(mappings, key) : null;
}
/**
* Returns a pair of identifier lists, also keeping track of whether the two lists are equal.
*
* @param unmappedTag unmapped mappings tag
* @param mappedTag mapped mappings tag
* @param key mappings key
* @return pair of identifier lists
*/
public @Nullable IdentifiersPair identifiersFromGlobalIds(final CompoundTag unmappedTag, final CompoundTag mappedTag, final String key) {
final Mappings unmapped = loadMappings(unmappedTag, key);
if (unmapped == null) {
if (mappings == null) {
return null;
}
final Mappings mapped = loadMappings(mappedTag, key);
if (mapped == null) {
return null;
}
final int size = unmapped.size();
if (size != mapped.size()) {
return new IdentifiersPair(identifiers(unmapped, key), identifiers(mapped, key), false);
}
// Small optimization to only load one array and reduce loading for full mappings
final List<String> unmappedIdentifiers = new ArrayList<>(size);
final List<String> mappedIdentifiers = new ArrayList<>(size);
boolean identity = true;
for (int i = 0; i < size; i++) {
final int unmappedGlobalId = unmapped.getNewId(i);
final int mappedGlobalId = mapped.getNewId(i);
final String unmappedIdentifier = identifierFromGlobalId(key, unmappedGlobalId);
if (unmappedGlobalId == mappedGlobalId) {
unmappedIdentifiers.add(unmappedIdentifier);
mappedIdentifiers.add(unmappedIdentifier);
continue;
}
if (mappedGlobalId == -1) {
throw new IllegalArgumentException("Mapped global id -1 for unmapped global id: " + key + "/" + unmappedIdentifier + " (" + unmappedGlobalId + ")");
}
identity = false;
unmappedIdentifiers.add(unmappedIdentifier);
mappedIdentifiers.add(identifierFromGlobalId(key, mappedGlobalId));
}
return identity ? new IdentifiersPair(unmappedIdentifiers) : new IdentifiersPair(unmappedIdentifiers, mappedIdentifiers);
}
private List<String> identifiers(final Mappings mappings, final String key) {
final int size = mappings.size();
final List<String> identifiers = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
final int globalId = mappings.getNewId(i);
identifiers.add(identifierFromGlobalId(key, globalId));
final List<String> identifiers = new ArrayList<>(mappings.size());
for (int i = 0; i < mappings.size(); i++) {
identifiers.add(identifierFromGlobalId(key, mappings.getNewId(i)));
}
return identifiers;
}
@@ -399,7 +295,7 @@ public class MappingDataLoader {
* @return map with indexes hashed by their id value
*/
public Object2IntMap<String> indexedObjectToMap(final JsonObject object) {
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(object.size());
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(object.size(), .99F);
map.defaultReturnValue(-1);
for (final Map.Entry<String, JsonElement> entry : object.entrySet()) {
map.put(entry.getValue().getAsString(), Integer.parseInt(entry.getKey()));
@@ -414,7 +310,7 @@ public class MappingDataLoader {
* @return map with indexes hashed by their id value
*/
public Object2IntMap<String> arrayToMap(final JsonArray array) {
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(array.size());
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(array.size(), .99F);
map.defaultReturnValue(-1);
for (int i = 0; i < array.size(); i++) {
map.put(array.get(i).getAsString(), i);
@@ -451,18 +347,4 @@ public class MappingDataLoader {
T create(V mappings, int mappedSize);
}
public record IdentifiersPair(List<String> unmapped, List<String> mapped, boolean identity) {
public IdentifiersPair(final List<String> unmapped, final List<String> mapped) {
this(unmapped, mapped, false);
}
public IdentifiersPair(final List<String> identifiers) {
this(identifiers, identifiers, true);
}
}
private record ValuePairs(int[] first, int[] second) {
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,8 +22,6 @@
*/
package com.viaversion.viaversion.api.data;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface Mappings {
/**
@@ -86,40 +84,4 @@ public interface Mappings {
* @return mappings with keys and values swapped
*/
Mappings inverse();
/**
* Returns whether the mappings are unchanged identity mappings.
*
* @return whether the mappings are unchanged identity mappings
*/
default boolean isIdentity() {
return false;
}
/**
* Returns whether the mappings null or identity mappings.
*
* @param mappings mappings
* @return whether the mappings are identity mappings
* @see #isFullIdentity(Mappings)
*/
static boolean isIntIdIdentity(@Nullable final Mappings mappings) {
if (mappings == null) {
return true;
}
return mappings instanceof FullMappings fullMappings ? fullMappings.isIntIdIdentity() : mappings.isIdentity();
}
/**
* Returns whether the mappings null or full identity mappings.
* Stronger than {@link #isIntIdIdentity(Mappings)}, but equal to that if not {@link FullMappings}.
*
* @param mappings mappings
* @return whether the mappings are full identity mappings
* @see #isIntIdIdentity(Mappings)
*/
static boolean isFullIdentity(@Nullable final Mappings mappings) {
return mappings == null || mappings.isIdentity();
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,21 +22,20 @@
*/
package com.viaversion.viaversion.api.data;
import com.viaversion.viaversion.api.data.MappingDataLoader.IdentifiersPair;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
public class ParticleMappings extends FullMappingsBase {
private final IntList itemParticleIds = new IntArrayList(4);
private final IntList blockParticleIds = new IntArrayList(4);
public ParticleMappings(final IdentifiersPair identifiersPair, final Mappings mappings) {
super(identifiersPair, mappings);
public ParticleMappings(final List<String> unmappedIdentifiers, final List<String> mappedIdentifiers, final Mappings mappings) {
super(unmappedIdentifiers, mappedIdentifiers, mappings);
addBlockParticle("block");
addBlockParticle("falling_dust");
addBlockParticle("block_marker");
addBlockParticle("dust_pillar");
addBlockParticle("block_crumble");
addItemParticle("item");
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,10 +23,7 @@
package com.viaversion.viaversion.api.data.entity;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.KeyMappings;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -45,9 +42,8 @@ public interface EntityTracker {
*
* @param id entity id
* @param type entity type
* @return tracked entity
*/
TrackedEntity addEntity(int id, EntityType type);
void addEntity(int id, EntityType type);
/**
* Returns whether the entity is currently tracked.
@@ -78,34 +74,39 @@ public interface EntityTracker {
* Untracks an entity.
*
* @param id entity id
* @return previously tracked entity
*/
@Nullable TrackedEntity removeEntity(int id);
void removeEntity(int id);
/**
* Clears stored entity types and data, only leaving behind the client entity.
* Clears stored entity types and data.
*/
void clearEntities();
/**
* Clears all stored data, including entity types, entity data and client entity id.
* Returns the stored entity data if an entity with the id is tracked, else null.
* If no data has been initialized yet, it will be done and returned by this method.
*
* @param id entity id
* @return stored entity data if an entity with the id is tracked, else null
* @throws IllegalArgumentException if entity data storage has not been enabled via the implementation
*/
void clear();
@Nullable StoredEntityData entityData(int id);
/**
* Returns whether the client entity id has been set.
* Returns stored entity data if it has previously been initialized by {@link #entityData(int)}, else null.
*
* @return whether the client entity id has been set
* @param id entity id
* @return stored entity data if it has previously been initialized by {@link #entityData(int)}
* @throws IllegalArgumentException if entity data storage has not been enabled via the implementation
*/
boolean hasClientEntityId();
@Nullable StoredEntityData entityDataIfPresent(int id);
/**
* Returns the client entity id. Should be wrapped around {@link #hasClientEntityId()}.
* Returns the client entity id or -1 if unset.
*
* @return client entity id
* @throws IllegalStateException if the client entity id has not been set
* @return client entity id or -1 if unset
*/
int clientEntityId() throws IllegalStateException;
int clientEntityId();
/**
* Sets the client entity id.
@@ -114,20 +115,6 @@ public interface EntityTracker {
*/
void setClientEntityId(int clientEntityId);
/**
* Returns whether the client player has the "insta build" ability, usually from creative mode.
*
* @return whether the client player can insta build
*/
boolean canInstaBuild();
/**
* Sets whether the client player has the "insta build" ability, usually from creative mode.
*
* @param instaBuild whether the client player can insta build
*/
void setInstaBuild(boolean instaBuild);
/**
* Returns the current world section height (block height / 16).
* This is always 16 for sub 1.17 worlds.
@@ -171,42 +158,10 @@ public interface EntityTracker {
*/
void setCurrentWorld(String currentWorld);
/**
* Returns the id of the current dimension, or -1 if unset (i.e. before 1.20.5).
*
* @return id of the current dimension, or -1 if unset
*/
int currentDimensionId();
/**
* Sets the id of the current dimension.
*
* @param currentDimensionId id of the current dimension
*/
void setCurrentDimensionId(int currentDimensionId);
int biomesSent();
void setBiomesSent(int biomesSent);
/**
* Returns the cached chunk type for the current dimension if set.
*
* @param mapped whether to return the mapped chunk type
* @return cached chunk type
*/
@Nullable Type<Chunk> chunkType(boolean mapped);
/**
* Caches the chunk type for the current dimension.
* <p>
* Invalidates when the world section height or the number of biomes change.
*
* @param mapped whether to set the mapped chunk type
* @param chunkType chunk type
*/
void setChunkType(boolean mapped, @Nullable Type<Chunk> chunkType);
EntityType playerType();
@Nullable DimensionData dimensionData(String dimension);
@@ -215,7 +170,11 @@ public interface EntityTracker {
void setDimensions(Map<String, DimensionData> dimensions);
@Nullable KeyMappings registryKeys(String registryKey);
void addRegistryKeys(String registryKey, KeyMappings mappings);
/**
* Adds the client player entity to the tracker.
* If the client entity has not been set yet, this will return false.
*
* @return whether the client has been tracked
*/
boolean trackClientEntity();
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -20,53 +20,50 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft.item;
package com.viaversion.viaversion.api.data.entity;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* @see Item
* @see HashedItem
*/
public interface ItemBase extends Copyable {
public interface StoredEntityData {
/**
* Returns the item identifier.
* Returns the entity type of the stored entity.
*
* @return item identifier
* @return entity type
*/
int identifier();
EntityType type();
/**
* Sets the item identifier.
* Checks if the storage contains an object of the given type.
*
* @param identifier item identifier
* @param objectClass object class to check
* @return whether an object of the given type is in the storage
*/
void setIdentifier(int identifier);
boolean has(Class<?> objectClass);
/**
* Returns the item amount.
* Returns an object from the storage if present.
*
* @return item amount
* @param objectClass class of the object to get
* @param <T> object type
* @return object if present
*/
int amount();
@Nullable <T> T get(Class<T> objectClass);
/**
* Returns the item amount.
* Removes and returns an object from the storage if present.
*
* @param amount item amount
* @param objectClass class of the object to remove
* @param <T> object type
* @return removed object if present
*/
void setAmount(int amount);
@Nullable <T> T remove(Class<T> objectClass);
/**
* Returns true if the item is empty.
* Stores an object based on its class.
*
* @return true if the item is empty
* @param object object to store
*/
default boolean isEmpty() {
return identifier() == 0 || amount() <= 0;
}
@Override
ItemBase copy();
}
void put(Object object);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,9 +22,7 @@
*/
package com.viaversion.viaversion.api.data.entity;
import com.viaversion.viaversion.api.connection.StorableObject;
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
import org.checkerframework.checker.nullness.qual.Nullable;
public interface TrackedEntity {
@@ -36,37 +34,18 @@ public interface TrackedEntity {
EntityType entityType();
/**
* Checks if the storage contains an object of the given type.
* Object to hold arbitrary additional data.
*
* @param objectClass object class to check
* @return whether an object of the given type is in the storage
* @return entity data
*/
boolean has(Class<? extends StorableObject> objectClass);
StoredEntityData data();
/**
* Returns an object from the storage if present.
* Returns whether the stored entity currently has any additional data.
*
* @param objectClass class of the object to get
* @param <T> object type
* @return object if present
* @return whether the stored entity currently has additional data
*/
@Nullable <T extends StorableObject> T get(Class<T> objectClass);
/**
* Removes and returns an object from the storage if present.
*
* @param objectClass class of the object to remove
* @param <T> object type
* @return removed object if present
*/
@Nullable <T extends StorableObject> T remove(Class<T> objectClass);
/**
* Stores an object based on its class.
*
* @param object object to store
*/
void put(StorableObject object);
boolean hasData();
/**
* Returns whether entity data has already been sent at least once for this entity.
@@ -76,4 +55,4 @@ public interface TrackedEntity {
boolean hasSentEntityData();
void sentEntityData(boolean sentEntityData);
}
}
@@ -1,42 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.data.item;
/**
* 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);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,6 +22,7 @@
*/
package com.viaversion.viaversion.api.debug;
import com.google.common.annotations.Beta;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.packet.PacketType;
@@ -49,14 +50,16 @@ public interface DebugHandler {
*
* @param packetTypeName packet type name
*/
@Beta
void addPacketTypeNameToLog(String packetTypeName);
/**
* Adds a packet type to the list of packet types to log.
* Adds a packet id to the list of packet types to log.
* Packets will be checked on each protocol transformer, so this is best used on single protocol pipes.
*
* @param packetType packet type
*/
@Beta
void addPacketTypeToLog(PacketType packetType);
/**
@@ -64,51 +67,22 @@ public interface DebugHandler {
*
* @param packetTypeName packet type name
*/
@Beta
boolean removePacketTypeNameToLog(String packetTypeName);
/**
* Removes a packet type from the list of packet types to log.
*
* @param packetType Packet type to remove
*/
boolean removePacketTypeToLog(PacketType packetType);
/**
* Resets packet type filters.
*/
@Beta
void clearPacketTypesToLog();
/**
* Sets whether packets should be logged before and after being transformed.
*
* @param logPacketTransform whether packets should be logged
*/
default void setLogPacketTransform(boolean logPacketTransform) {
setLogPrePacketTransform(logPacketTransform);
setLogPostPacketTransform(logPacketTransform);
}
/**
* Returns whether packets should be logged before being transformed.
* Set to true by default.
*
* @return whether packets should be logged before being transformed
*/
boolean logPrePacketTransform();
/**
* Sets whether packets should be logged before being transformed.
*
* @param logPrePacketTransform whether packets should be logged before being transformed
*/
void setLogPrePacketTransform(boolean logPrePacketTransform);
/**
* Returns whether packets should be logged after being transformed.
* Set to false by default.
* Set to true by default.
*
* @return whether packets should be logged after being transformed
*/
@Beta
boolean logPostPacketTransform();
/**
@@ -116,6 +90,7 @@ public interface DebugHandler {
*
* @param logPostPacketTransform whether packets should be logged after being transformed
*/
@Beta
void setLogPostPacketTransform(boolean logPostPacketTransform);
/**
@@ -128,12 +103,8 @@ public interface DebugHandler {
*/
boolean shouldLog(PacketWrapper wrapper, Direction direction);
/**
* Enables debug mode and adds the given packet types to the log list.
*
* @param packetTypes packet types to log
*/
default void enableAndLogTypes(final PacketType... packetTypes) {
@Beta
default void enableAndLogIds(final PacketType... packetTypes) {
setEnabled(true);
for (final PacketType packetType : packetTypes) {
addPacketTypeToLog(packetType);
@@ -147,7 +118,7 @@ public interface DebugHandler {
* @param t thrown exception
*/
default void error(final String error, final Throwable t) {
if (Via.getConfig().logOtherConversionWarnings() || enabled()) {
if (!Via.getConfig().isSuppressConversionWarnings() || enabled()) {
Via.getPlatform().getLogger().log(Level.SEVERE, error, t);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,55 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents an animal variant (e.g. for cows, pigs, chickens).
*
* @param modelType model type id
* @param texture texture path
* @param biomes biomes this variant can spawn in, if limited to specific biomes
*/
public record AnimalVariant(int modelType, String texture, @Nullable HolderSet biomes) {
public static HolderType<AnimalVariant> TYPE = new HolderType<>() {
@Override
public AnimalVariant readDirect(final ByteBuf buffer) {
final int modelType = Types.VAR_INT.readPrimitive(buffer);
final String texture = Types.STRING.read(buffer);
final HolderSet biomes = Types.OPTIONAL_HOLDER_SET.read(buffer);
return new AnimalVariant(modelType, texture, biomes);
}
@Override
public void writeDirect(final ByteBuf buffer, final AnimalVariant variant) {
Types.VAR_INT.writePrimitive(buffer, variant.modelType());
Types.STRING.write(buffer, variant.texture());
Types.OPTIONAL_HOLDER_SET.write(buffer, variant.biomes());
}
};
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -65,4 +65,4 @@ public interface BlockChangeRecord {
int getBlockId();
void setBlockId(int blockId);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -58,7 +58,7 @@ public class BlockChangeRecord1_16_2 implements BlockChangeRecord {
@Override
public short getY(int chunkSectionY) {
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: %s", chunkSectionY);
Preconditions.checkArgument(chunkSectionY >= 0, "Invalid chunkSectionY: " + chunkSectionY);
return (short) ((chunkSectionY << 4) + sectionY);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -33,6 +33,7 @@ public enum BlockFace {
TOP((byte) 0, (byte) 1, (byte) 0, EnumAxis.Y),
BOTTOM((byte) 0, (byte) -1, (byte) 0, EnumAxis.Y);
public static final BlockFace[] HORIZONTAL = {NORTH, SOUTH, EAST, WEST};
private static final Map<BlockFace, BlockFace> opposites = new EnumMap<>(BlockFace.class);
static {
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -37,13 +37,6 @@ public class BlockPosition {
return new BlockPosition(x + face.modX(), y + face.modY(), z + face.modZ());
}
public double distanceFromCenterSquared(final double x, final double y, final double z) {
final double dx = this.x + 0.5 - x;
final double dy = this.y + 0.5 - y;
final double dz = this.z + 0.5 - z;
return dx * dx + dy * dy + dz * dz;
}
public int x() {
return x;
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -66,17 +66,6 @@ public final class ChunkPosition {
return (long) chunkX & 0xffffffffL | ((long) chunkZ & 0xffffffffL) << 32;
}
/**
* Returns a long key for the given block coordinates.
*
* @param x the block X coordinate
* @param z the block Z coordinate
* @return the chunk key
*/
public static long chunkKeyForBlock(final int x, final int z) {
return chunkKey(x >> 4, z >> 4);
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,12 +23,13 @@
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.connection.StorableObject;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Stored up until 1.14 to be used in chunk sending.
*/
public class ClientWorld implements StorableObject {
private Environment environment = Environment.NORMAL;
private Environment environment;
public ClientWorld() {
}
@@ -37,20 +38,11 @@ public class ClientWorld implements StorableObject {
this.environment = environment;
}
public Environment getEnvironment() {
public @Nullable Environment getEnvironment() {
return environment;
}
/**
* Sets the environment of the world and returns whether the environment was changed.
*
* @param environmentId the id of the environment to set
* @return whether the environment was changed
*/
public boolean setEnvironment(final int environmentId) {
final int previousEnvironmentId = environment.id();
public void setEnvironment(final int environmentId) {
this.environment = Environment.getEnvironmentById(environmentId);
return previousEnvironmentId != environmentId;
}
}
@@ -1,82 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
public interface EitherHolder<T> {
/**
* Returns a direct or indirect value holder.
*
* @param value the value
* @param <T> the type of the value
* @return a new direct holder
*/
static <T> EitherHolder<T> of(final Holder<T> value) {
return new EitherHolderImpl<>(value, null);
}
/**
* Returns an indirect holder via the resource key.
*
* @param key the resource key
* @param <T> the type of the value
* @return a new holder with the given resource key
*/
static <T> EitherHolder<T> of(final String key) {
return new EitherHolderImpl<>(null, key);
}
/**
* Returns true if this holder is backed by a direct value.
*
* @return true if the holder is direct
* @see #hasKey()
*/
boolean hasHolder();
/**
* Returns true if this holder has a resource key.
*
* @return true if this holder has a resource key
* @see #hasHolder()
*/
boolean hasKey();
/**
* Returns the value of this holder.
*
* @return the value of this holder
* @throws IllegalArgumentException if this contains a resource key instead of a holder
* @see #hasHolder()
*/
Holder<T> holder();
/**
* Returns the resource key.
*
* @return the resource key
* @throws IllegalArgumentException if this contains a holder instead of a resource key
* @see #hasKey()
*/
String key();
}
@@ -1,55 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import com.viaversion.viaversion.util.EitherImpl;
final class EitherHolderImpl<T> extends EitherImpl<Holder<T>, String> implements EitherHolder<T> {
EitherHolderImpl(final Holder<T> left, final String value) {
super(left, value);
}
@Override
public boolean hasHolder() {
return isLeft();
}
@Override
public boolean hasKey() {
return isRight();
}
@Override
public Holder<T> holder() {
Preconditions.checkArgument(hasHolder(), "Either does not have a holder");
return left();
}
@Override
public String key() {
Preconditions.checkArgument(hasKey(), "Either does not have a key");
return right();
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,35 +24,28 @@ package com.viaversion.viaversion.api.minecraft;
public enum GameMode {
NOT_SET("", -1),
SURVIVAL("Survival Mode", 0),
CREATIVE("Creative Mode", 1),
ADVENTURE("Adventure Mode", 2),
SPECTATOR("Spectator Mode", 3);
SURVIVAL("Survival Mode"),
CREATIVE("Creative Mode"),
ADVENTURE("Adventure Mode"),
SPECTATOR("Spectator Mode");
private final String text;
private final int id;
GameMode(String text, final int id) {
GameMode(String text) {
this.text = text;
this.id = id;
}
public String text() {
return text;
}
public int id() {
return id;
}
public static GameMode getById(int id) {
return switch (id) {
case -1 -> NOT_SET;
case 0 -> SURVIVAL;
case 1 -> CREATIVE;
case 2 -> ADVENTURE;
case 3 -> SPECTATOR;
default /*0*/ -> SURVIVAL;
default -> throw new IllegalArgumentException("Unknown gamemode id: " + id);
};
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,35 +22,11 @@
*/
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, boolean dynamic) {
public GameProfile(@Nullable final String name, @Nullable final UUID id, final Property[] properties) {
this(name, id, properties, true);
}
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 GameProfile(@Nullable String name, @Nullable UUID id, Property[] properties) {
public record Property(String name, String value, @Nullable String signature) {
public Property(final String name, final String value) {
this(name, value, null);
}
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,10 +22,6 @@
*/
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> {
/**
@@ -37,7 +33,7 @@ public interface Holder<T> {
* @throws IllegalArgumentException if the id is negative
*/
static <T> Holder<T> of(final int id) {
return new IdHolder<>(id);
return new HolderImpl<>(id);
}
/**
@@ -48,7 +44,7 @@ public interface Holder<T> {
* @return a new direct holder
*/
static <T> Holder<T> of(final T value) {
return new ValueHolder<>(value);
return new HolderImpl<>(value);
}
/**
@@ -83,31 +79,4 @@ public interface Holder<T> {
* @see #hasId()
*/
int id();
/**
* 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
* @return a new holder with the id rewritten, or self
*/
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);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,35 +22,50 @@
*/
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import com.google.common.base.Preconditions;
record ValueHolder<T>(T value) implements Holder<T> {
final class HolderImpl<T> implements Holder<T> {
private final T value;
private final int id;
HolderImpl(final int id) {
Preconditions.checkArgument(id >= 0, "id cannot be negative");
this.value = null;
this.id = id;
}
HolderImpl(final T value) {
this.value = value;
this.id = -1;
}
@Override
public boolean isDirect() {
return true;
return id == -1;
}
@Override
public boolean hasId() {
return false;
return id != -1;
}
@Override
public T value() {
Preconditions.checkArgument(isDirect(), "Holder is not direct");
return value;
}
@Override
public int id() {
return -1;
return id;
}
@Override
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;
public String toString() {
return "HolderImpl{" +
"value=" + value +
", id=" + id +
'}';
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,13 +22,6 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.google.common.base.Preconditions;
import com.viaversion.nbt.tag.ListTag;
import com.viaversion.nbt.tag.StringTag;
import com.viaversion.nbt.tag.Tag;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.function.ToIntFunction;
/**
* Set of ids that either holds a string tag key or an array of ids.
*/
@@ -37,12 +30,11 @@ public interface HolderSet {
/**
* Creates a new holder set for the given tag.
*
* @param tagKey the tag key, not including '#'
* @param tagKey the tag key
* @return a new holder set
*/
static HolderSet of(final String tagKey) {
Preconditions.checkNotNull(tagKey);
return new HolderSetImpl.Tag(tagKey);
return new HolderSetImpl(tagKey);
}
/**
@@ -52,33 +44,13 @@ public interface HolderSet {
* @return a new holder set
*/
static HolderSet of(final int[] ids) {
Preconditions.checkNotNull(ids);
return new HolderSetImpl.Ids(ids);
}
static HolderSet fromTag(final Tag tag, final ToIntFunction<String> mappingFunction) {
if (tag instanceof StringTag stringTag) {
if (stringTag.getValue().startsWith("#")) {
return HolderSet.of(stringTag.getValue().substring(1));
}
final int id = mappingFunction.applyAsInt(stringTag.getValue());
return HolderSet.of(new int[]{id});
} else if (tag instanceof ListTag<?> listTag) {
final int[] ids = new int[listTag.size()];
for (int i = 0; i < listTag.size(); i++) {
final String value = ((StringTag) listTag.get(i)).getValue();
ids[i] = mappingFunction.applyAsInt(value);
}
return HolderSet.of(ids);
}
throw new IllegalArgumentException();
return new HolderSetImpl(ids);
}
/**
* Gets the tag key, not including '#'.
* Gets the tag key.
*
* @return the tag key without a '#'
* @return the tag key
* @see #hasTagKey()
*/
String tagKey();
@@ -104,12 +76,4 @@ public interface HolderSet {
* @return true if this holder set has direct ids, false if it has a tag key
*/
boolean hasIds();
/**
* Returns a new holder set with the ids rewritten.
*
* @param idRewriter the id rewriter
* @return a new holder set with the ids rewritten, or self if it has a tag key
*/
HolderSet rewrite(Int2IntFunction idRewriter);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,69 +22,35 @@
*/
package com.viaversion.viaversion.api.minecraft;
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
import java.util.Arrays;
import com.viaversion.viaversion.util.EitherImpl;
final class HolderSetImpl {
final class HolderSetImpl extends EitherImpl<String, int[]> implements HolderSet {
record Tag(String tagKey) implements HolderSet {
@Override
public boolean hasTagKey() {
return true;
}
@Override
public int[] ids() {
throw new IllegalArgumentException("This holder set has a tag key");
}
@Override
public boolean hasIds() {
return false;
}
@Override
public HolderSet rewrite(final Int2IntFunction idRewriter) {
return this;
}
HolderSetImpl(final String tagKey) {
super(tagKey, null);
}
record Ids(int[] ids) implements HolderSet {
@Override
public boolean hasTagKey() {
return false;
}
HolderSetImpl(final int[] ids) {
super(null, ids);
}
@Override
public String tagKey() {
throw new IllegalArgumentException("This holder set has direct ids");
}
@Override
public String tagKey() {
return left();
}
@Override
public boolean hasIds() {
return true;
}
@Override
public boolean hasTagKey() {
return isLeft();
}
@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];
int validCount = 0;
for (final int id : ids) {
final int mappedId = idRewriter.applyAsInt(id);
if (mappedId != -1) {
mappedIds[validCount++] = mappedId;
}
}
return new Ids(validCount == ids.length ? mappedIds : Arrays.copyOf(mappedIds, validCount));
}
@Override
public int[] ids() {
return right();
}
@Override
public String toString() {
return "Ids{" +
"ids=" + Arrays.toString(ids) +
'}';
}
@Override
public boolean hasIds() {
return isRight();
}
}
@@ -1,70 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
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> {
IdHolder {
Preconditions.checkArgument(id >= 0, "id cannot be negative");
}
@Override
public boolean isDirect() {
return false;
}
@Override
public boolean hasId() {
return true;
}
@Override
public T value() {
throw new IllegalArgumentException("Holder is not direct");
}
@Override
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;
}
}
@@ -1,91 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.minecraft.codec.Ops;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import com.viaversion.viaversion.util.Key;
import io.netty.buffer.ByteBuf;
import org.checkerframework.checker.nullness.qual.Nullable;
public record PaintingVariant(int width, int height, String assetId, @Nullable Tag title, @Nullable Tag author) {
public PaintingVariant(final int width, final int height, final String assetId) {
this(width, height, assetId, null, null);
}
public static HolderType<PaintingVariant> TYPE1_21 = new HolderType<>() {
@Override
public PaintingVariant readDirect(final ByteBuf buffer) {
final int width = Types.VAR_INT.readPrimitive(buffer);
final int height = Types.VAR_INT.readPrimitive(buffer);
final String assetId = Types.STRING.read(buffer);
return new PaintingVariant(width, height, assetId);
}
@Override
public void writeDirect(final ByteBuf buffer, final PaintingVariant variant) {
Types.VAR_INT.writePrimitive(buffer, variant.width());
Types.VAR_INT.writePrimitive(buffer, variant.height());
Types.STRING.write(buffer, variant.assetId());
}
};
public static HolderType<PaintingVariant> TYPE1_21_2 = new HolderType<>() {
@Override
public PaintingVariant readDirect(final ByteBuf buffer) {
final int width = Types.VAR_INT.readPrimitive(buffer);
final int height = Types.VAR_INT.readPrimitive(buffer);
final String assetId = Types.STRING.read(buffer);
final Tag title = Types.TRUSTED_OPTIONAL_TAG.read(buffer);
final Tag author = Types.TRUSTED_OPTIONAL_TAG.read(buffer);
return new PaintingVariant(width, height, assetId, title, author);
}
@Override
public void writeDirect(final ByteBuf buffer, final PaintingVariant variant) {
Types.VAR_INT.writePrimitive(buffer, variant.width());
Types.VAR_INT.writePrimitive(buffer, variant.height());
Types.STRING.write(buffer, variant.assetId());
Types.TRUSTED_OPTIONAL_TAG.write(buffer, variant.title());
Types.TRUSTED_OPTIONAL_TAG.write(buffer, variant.author());
}
@Override
public void writeDirect(final Ops ops, final PaintingVariant value) {
// Unused, cannot be direct despite having a direct network codec
ops.writeMap(map -> map
.write("width", Types.INT, value.width())
.write("height", Types.INT, value.height())
.write("asset_id", Types.IDENTIFIER, Key.of(value.assetId()))
.writeOptional("title", Types.TEXT_COMPONENT_TAG, value.title())
.writeOptional("author", Types.TEXT_COMPONENT_TAG, value.author()));
}
@Override
protected Key identifier(final Ops ops, final int id) {
return ops.context().registryAccess().registryKey("painting_variant", id);
}
};
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,13 +24,12 @@ package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.util.Copyable;
import com.viaversion.viaversion.util.IdHolder;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
public final class Particle implements IdHolder, Copyable {
public final class Particle implements IdHolder {
private final List<ParticleData<?>> arguments = new ArrayList<>(4);
private int id;
@@ -73,15 +72,6 @@ public final class Particle implements IdHolder, Copyable {
arguments.set(index, new ParticleData<>(type, value));
}
@Override
public Particle copy() {
final Particle particle = new Particle(id);
for (ParticleData<?> argument : arguments) {
particle.arguments.add(argument.copy());
}
return particle;
}
@Override
public String toString() {
return "Particle{" +
@@ -90,7 +80,7 @@ public final class Particle implements IdHolder, Copyable {
'}';
}
public static final class ParticleData<T> implements Copyable {
public static final class ParticleData<T> {
private final Type<T> type;
private T value;
@@ -119,11 +109,6 @@ public final class Particle implements IdHolder, Copyable {
wrapper.write(type, value);
}
@Override
public ParticleData<T> copy() {
return new ParticleData<>(type, Copyable.copy(value));
}
@Override
public String toString() {
return "ParticleData{" +
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -23,23 +23,11 @@
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.util.Copyable;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Represents an entry in a registry.
*
* @param key key of the registry entry
* @param tag data of the registry entry, or null if the client should use its default
*/
public record RegistryEntry(String key, @Nullable Tag tag) implements Copyable {
public record RegistryEntry(String key, @Nullable Tag tag) {
public RegistryEntry withKey(final String key) {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
@Override
public RegistryEntry copy() {
return new RegistryEntry(key, tag != null ? tag.copy() : null);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,28 +22,24 @@
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.Key;
import java.util.HashMap;
import java.util.Map;
import org.checkerframework.checker.nullness.qual.Nullable;
public enum RegistryType implements RegistryKey {
public enum RegistryType {
BLOCK("block"),
ITEM("item"),
FLUID("fluid"),
ENTITY("entity_type"),
GAME_EVENT("game_event"),
ENCHANTMENT("enchantment"),
DAMAGE_TYPE("damage_type"),
BANNER_PATTERN("banner_pattern");
GAME_EVENT("game_event");
private static final Map<String, RegistryType> MAP = new HashMap<>();
private static final RegistryType[] VALUES = values();
static {
for (RegistryType type : getValues()) {
MAP.put(type.identifier(), type);
MAP.put(type.resourceLocation, type);
}
}
@@ -51,22 +47,17 @@ public enum RegistryType implements RegistryKey {
return VALUES;
}
public static @Nullable RegistryType getByKey(String identifier) {
return MAP.get(identifier);
public static @Nullable RegistryType getByKey(String resourceKey) {
return MAP.get(resourceKey);
}
private final Key key;
private final String resourceLocation;
RegistryType(final String identifier) {
this.key = Key.of(identifier);
RegistryType(final String resourceLocation) {
this.resourceLocation = resourceLocation;
}
public String identifier() {
return key.path();
}
@Override
public Key registry() {
return this.key;
public String resourceLocation() {
return resourceLocation;
}
}
@@ -1,40 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.EitherImpl;
public final class ResolvableFloat extends EitherImpl<Float, String> {
private ResolvableFloat(final Float left, final String right) {
super(left, right);
}
public static ResolvableFloat of(final String value) {
return new ResolvableFloat(null, value);
}
public static ResolvableFloat of(final Float value) {
return new ResolvableFloat(value, null);
}
}
@@ -1,40 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.EitherImpl;
public final class ResolvableInt extends EitherImpl<Integer, String> {
private ResolvableInt(final Integer left, final String right) {
super(left, right);
}
public static ResolvableInt of(final String value) {
return new ResolvableInt(null, value);
}
public static ResolvableInt of(final Integer value) {
return new ResolvableInt(value, null);
}
}
@@ -1,37 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Profile that can be either dynamically filled by the client or is already static.
* The additional fields are optional overrides.
*/
public record ResolvableProfile(GameProfile profile, @Nullable String bodyTexture, @Nullable String capeTexture,
@Nullable String elytraTexture, @Nullable Integer modelType) {
public ResolvableProfile(final GameProfile profile) {
this(profile, null, null, null, null);
}
}
@@ -1,33 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.util.Key;
record SimpleRegistryKey(Key registry) implements RegistryKey {
@Override
public String toString() {
return registry.toString();
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,28 +22,11 @@
*/
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);
}
public static @Nullable Holder<SoundEvent> rewriteOptionalHolder(@Nullable final Holder<SoundEvent> holder, final Int2IntFunction soundRewriteFunction) {
if (holder == null) {
return null;
}
return holder.updateId(soundRewriteFunction, () -> null);
}
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,28 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
public record Vector3d(double x, double y, double z) {
public static final Vector3d ZERO = new Vector3d(0, 0, 0);
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,49 +0,0 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.viaversion.viaversion.api.minecraft;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.misc.HolderType;
import io.netty.buffer.ByteBuf;
public record WolfVariant(String wildTexture, String tameTexture, String angryTexture, HolderSet biomes) {
public static HolderType<WolfVariant> TYPE = new HolderType<>() {
@Override
public WolfVariant readDirect(final ByteBuf buffer) {
final String wildTexture = Types.STRING.read(buffer);
final String tameTexture = Types.STRING.read(buffer);
final String angryTexture = Types.STRING.read(buffer);
final HolderSet biomes = Types.HOLDER_SET.read(buffer);
return new WolfVariant(wildTexture, tameTexture, angryTexture, biomes);
}
@Override
public void writeDirect(final ByteBuf buffer, final WolfVariant variant) {
Types.STRING.write(buffer, variant.wildTexture());
Types.STRING.write(buffer, variant.tameTexture());
Types.STRING.write(buffer, variant.angryTexture());
Types.HOLDER_SET.write(buffer, variant.biomes());
}
};
}
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
/*
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
* Copyright (C) 2016-2026 ViaVersion and contributors
* Copyright (C) 2016-2024 ViaVersion and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Loaded 100 of 1257 files, more files were not shown because too many files have changed in this diff. Show more