mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2026-11-04 08:52:10 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c09fa331c6
|
||
|
|
0088f657e7
|
||
|
|
0f95f7cbaf | ||
|
|
e607988751 | ||
|
|
d05985fdb3 | ||
|
|
2bb90d32da | ||
|
|
e59c12cf62 | ||
|
|
1f6103aa9b | ||
|
|
00bb773c4a | ||
|
|
b4d8fe6ba1 | ||
|
|
cab919bfaf | ||
|
|
9d9fe03317 | ||
|
|
8fd09c8ba4 | ||
|
|
4802926441 | ||
|
|
5628bcbb83 | ||
|
|
33062af729 | ||
|
|
f32dca9b56 | ||
|
|
a09fa97f42 | ||
|
|
08100010c7 | ||
|
|
9a8a01b753 | ||
|
|
c95c839bb0 | ||
|
|
3e8682f948 | ||
|
|
1e2c5dbb7a | ||
|
|
a11d7eb783 | ||
|
|
40554ef505 | ||
|
|
6ce21135fb | ||
|
|
315a987f4f | ||
|
|
333a373fcc | ||
|
|
8c57534432 | ||
|
|
686e6902fd | ||
|
|
e15fc5953e | ||
|
|
c611a34e76 | ||
|
|
567ef33f6f | ||
|
|
bc0fc7884d | ||
|
|
b3d560bd3a | ||
|
|
4738945a7a | ||
|
|
4c55ef9cab | ||
|
|
a66dbf77aa | ||
|
|
c6cc380c3c | ||
|
|
cd3f146781 | ||
|
|
d0da13edd8 | ||
|
|
ec1f570f4b | ||
|
|
e41e216903 | ||
|
|
43ee417e20 | ||
|
|
4dc57e3d53 | ||
|
|
31f257fee1 | ||
|
|
cda72574fc | ||
|
|
ef1b6a10ea | ||
|
|
c45c700301 | ||
|
|
c43de2b88d | ||
|
|
898b6c8774 | ||
|
|
2e3c47d292 | ||
|
|
7974d1a570 | ||
|
|
cf2c1c5b76 | ||
|
|
d75c54cc70 | ||
|
|
ead13b2bb9 | ||
|
|
2e91b841b0 | ||
|
|
50486fa43a | ||
|
|
31d4cd453d | ||
|
|
c5482b99bf | ||
|
|
98ef806887 | ||
|
|
a26745862f | ||
|
|
6bd081cefd | ||
|
|
bb9aa8b31c | ||
|
|
572f7a2677 | ||
|
|
11a5c9e32c | ||
|
|
02b65dcb36 | ||
|
|
0121534e7e | ||
|
|
941e6f6df4 | ||
|
|
fe6e18845b | ||
|
|
8f8f5e72c0 |
No files matched your search
@@ -0,0 +1 @@
|
||||
@../AGENTS.md
|
||||
@@ -0,0 +1 @@
|
||||
.gitea/CODEOWNERS linguist-detectable=false
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pull requests request review from the eligible staff team(s).
|
||||
# One approval from either an Admin or Developer satisfies branch protection.
|
||||
* @trueog/Admins @trueog/Developers
|
||||
@@ -11,13 +11,16 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # 5.0.1
|
||||
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
||||
with:
|
||||
cache-disabled: false
|
||||
cache-provider: basic
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
@@ -27,7 +30,7 @@ jobs:
|
||||
- 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@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 6.0.0
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: Artifacts
|
||||
path: build/libs/
|
||||
|
||||
@@ -16,13 +16,16 @@ jobs:
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@f29f5a9d7b09a7c6b29859002d29d24e1674c884 # 5.0.1
|
||||
uses: gradle/actions/setup-gradle@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
||||
with:
|
||||
cache-disabled: false
|
||||
cache-provider: basic
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 5.2.0
|
||||
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
|
||||
@@ -19,6 +19,8 @@ classes/
|
||||
*.ipr
|
||||
*.iws
|
||||
|
||||
benchmark/
|
||||
|
||||
# VSCode
|
||||
|
||||
.settings/
|
||||
@@ -34,3 +36,4 @@ bin/
|
||||
# Misc
|
||||
|
||||
run/
|
||||
AGENTS.override.md
|
||||
@@ -0,0 +1,22 @@
|
||||
# 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**
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2025 ViaVersion and contributors
|
||||
* 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
|
||||
|
||||
@@ -37,6 +37,7 @@ public interface ViaVersionCommand {
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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.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 org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class FullIdentityMappings implements FullMappings {
|
||||
private static final String[] EMPTY_ARRAY = new String[0];
|
||||
private final Object2IntMap<String> stringToId;
|
||||
private final String[] idToString;
|
||||
private final Mappings mappings;
|
||||
|
||||
public FullIdentityMappings(final IdentifiersPair identifiersPair, final Mappings mappings) {
|
||||
Preconditions.checkNotNull(mappings, "Mappings cannot be null");
|
||||
this.mappings = mappings;
|
||||
this.stringToId = FullMappingsBase.toInverseMap(identifiersPair.unmapped());
|
||||
this.idToString = identifiersPair.unmapped().toArray(EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
private FullIdentityMappings(final Object2IntMap<String> stringToId, final String[] idToString, final Mappings mappings) {
|
||||
this.stringToId = stringToId;
|
||||
this.idToString = idToString;
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id(final String identifier) {
|
||||
return stringToId.getInt(Key.stripMinecraftNamespace(identifier));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int mappedId(final String mappedIdentifier) {
|
||||
return id(mappedIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifier(final int id) {
|
||||
if (id < 0 || id >= idToString.length) {
|
||||
return null;
|
||||
}
|
||||
final String identifier = idToString[id];
|
||||
return Key.namespaced(identifier);
|
||||
}
|
||||
|
||||
@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) {
|
||||
return identifier(mappedId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String mappedIdentifier(final String identifier) {
|
||||
return identifier(identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewId(int id) {
|
||||
return mappings.getNewId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNewId(int id, int mappedId) {
|
||||
mappings.setNewId(id, mappedId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return mappings.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int mappedSize() {
|
||||
return mappings.mappedSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIntIdIdentity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullMappings inverse() {
|
||||
return new FullIdentityMappings(stringToId, idToString, mappings.inverse());
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,14 @@ public interface FullMappings extends BiMappings {
|
||||
*/
|
||||
@Nullable String mappedIdentifier(String identifier);
|
||||
|
||||
/**
|
||||
* Returns whether the int id mappings are identity mappings.
|
||||
*
|
||||
* @return whether the int id mappings are identity mappings
|
||||
* @see #isIdentity()
|
||||
*/
|
||||
boolean isIntIdIdentity();
|
||||
|
||||
@Override
|
||||
FullMappings inverse();
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
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;
|
||||
@@ -37,13 +38,13 @@ public class FullMappingsBase implements FullMappings {
|
||||
private final String[] mappedIdToString;
|
||||
private final Mappings mappings;
|
||||
|
||||
public FullMappingsBase(final List<String> unmappedIdentifiers, final List<String> mappedIdentifiers, final Mappings mappings) {
|
||||
public FullMappingsBase(final IdentifiersPair identifiersPair, final Mappings mappings) {
|
||||
Preconditions.checkNotNull(mappings, "Mappings cannot be null");
|
||||
this.mappings = mappings;
|
||||
this.stringToId = toInverseMap(unmappedIdentifiers);
|
||||
this.mappedStringToId = toInverseMap(mappedIdentifiers);
|
||||
this.idToString = unmappedIdentifiers.toArray(EMPTY_ARRAY);
|
||||
this.mappedIdToString = mappedIdentifiers.toArray(EMPTY_ARRAY);
|
||||
this.stringToId = toInverseMap(identifiersPair.unmapped());
|
||||
this.idToString = identifiersPair.unmapped().toArray(EMPTY_ARRAY);
|
||||
this.mappedStringToId = toInverseMap(identifiersPair.mapped());
|
||||
this.mappedIdToString = identifiersPair.mapped().toArray(EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
private FullMappingsBase(final Object2IntMap<String> stringToId, final Object2IntMap<String> mappedStringToId, final String[] idToString, final String[] mappedIdToString, final Mappings mappings) {
|
||||
@@ -54,7 +55,11 @@ public class FullMappingsBase implements FullMappings {
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
private static Object2IntMap<String> toInverseMap(final List<String> list) {
|
||||
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) {
|
||||
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(list.size());
|
||||
map.defaultReturnValue(-1);
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
@@ -135,6 +140,11 @@ public class FullMappingsBase implements FullMappings {
|
||||
return mappings.mappedSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIntIdIdentity() {
|
||||
return mappings.isIdentity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FullMappings inverse() {
|
||||
return new FullMappingsBase(mappedStringToId, stringToId, mappedIdToString, idToString, mappings.inverse());
|
||||
|
||||
@@ -38,4 +38,9 @@ public record IdentityMappings(int size, int mappedSize) implements Mappings {
|
||||
public Mappings inverse() {
|
||||
return new IdentityMappings(mappedSize, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdentity() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.IntArrayTag;
|
||||
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;
|
||||
@@ -96,14 +97,13 @@ public class MappingDataBase implements MappingData {
|
||||
attributeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "attributes");
|
||||
blockEntityMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "blockentities");
|
||||
|
||||
final List<String> unmappedParticles = identifiersFromGlobalIds(unmappedIdentifierData, "particles");
|
||||
final List<String> mappedParticles = identifiersFromGlobalIds(mappedIdentifierData, "particles");
|
||||
if (unmappedParticles != null && mappedParticles != null) {
|
||||
final IdentifiersPair particleIdentifiers = identifiersFromGlobalIds(unmappedIdentifierData, mappedIdentifierData, "particles");
|
||||
if (particleIdentifiers != null) {
|
||||
Mappings particleMappings = loadMappings(data, "particles");
|
||||
if (particleMappings == null) {
|
||||
particleMappings = new IdentityMappings(unmappedParticles.size(), mappedParticles.size());
|
||||
particleMappings = new IdentityMappings(particleIdentifiers.unmapped().size(), particleIdentifiers.mapped().size());
|
||||
}
|
||||
this.particleMappings = new ParticleMappings(unmappedParticles, mappedParticles, particleMappings);
|
||||
this.particleMappings = new ParticleMappings(particleIdentifiers, particleMappings);
|
||||
}
|
||||
} else {
|
||||
// Might not have identifiers in older versions
|
||||
@@ -132,6 +132,10 @@ 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);
|
||||
}
|
||||
@@ -158,14 +162,12 @@ public class MappingDataBase implements MappingData {
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<String> unmappedIdentifiers = identifiersFromGlobalIds(unmappedIdentifiersTag, key);
|
||||
final List<String> mappedIdentifiers = identifiersFromGlobalIds(mappedIdentifiersTag, key);
|
||||
final IdentifiersPair identifiersPair = identifiersFromGlobalIds(unmappedIdentifiersTag, mappedIdentifiersTag, key);
|
||||
Mappings mappings = loadBiMappings(data, key); // Load as bi-mappings to keep the inverse cached
|
||||
if (mappings == null) {
|
||||
mappings = new IdentityMappings(unmappedIdentifiers.size(), mappedIdentifiers.size());
|
||||
mappings = new IdentityMappings(identifiersPair.unmapped().size(), identifiersPair.mapped().size());
|
||||
}
|
||||
|
||||
return new FullMappingsBase(unmappedIdentifiers, mappedIdentifiers, mappings);
|
||||
return FullMappingsBase.of(identifiersPair, mappings);
|
||||
}
|
||||
|
||||
protected @Nullable BiMappings loadBiMappings(final CompoundTag data, final String key) {
|
||||
|
||||
@@ -81,8 +81,9 @@ public class MappingDataLoader {
|
||||
for (final Map.Entry<String, Tag> entry : globalIdentifiers.entrySet()) {
|
||||
//noinspection unchecked
|
||||
final ListTag<StringTag> value = (ListTag<StringTag>) entry.getValue();
|
||||
final String[] array = new String[value.size()];
|
||||
for (int i = 0, size = value.size(); i < size; i++) {
|
||||
final int size = value.size();
|
||||
final String[] array = new String[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
array[i] = value.get(i).getValue();
|
||||
}
|
||||
GLOBAL_IDENTIFIER_INDEXES.put(entry.getKey(), array);
|
||||
@@ -272,13 +273,60 @@ public class MappingDataLoader {
|
||||
|
||||
public @Nullable List<String> identifiersFromGlobalIds(final CompoundTag mappingsTag, final String key) {
|
||||
final Mappings mappings = loadMappings(mappingsTag, key);
|
||||
if (mappings == null) {
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
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 List<String> identifiers = new ArrayList<>(mappings.size());
|
||||
for (int i = 0; i < mappings.size(); i++) {
|
||||
identifiers.add(identifierFromGlobalId(key, mappings.getNewId(i)));
|
||||
final int globalId = mappings.getNewId(i);
|
||||
identifiers.add(identifierFromGlobalId(key, globalId));
|
||||
}
|
||||
return identifiers;
|
||||
}
|
||||
@@ -342,4 +390,15 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.data;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public interface Mappings {
|
||||
|
||||
/**
|
||||
@@ -84,4 +86,40 @@ 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();
|
||||
}
|
||||
}
|
||||
@@ -22,16 +22,16 @@
|
||||
*/
|
||||
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 List<String> unmappedIdentifiers, final List<String> mappedIdentifiers, final Mappings mappings) {
|
||||
super(unmappedIdentifiers, mappedIdentifiers, mappings);
|
||||
public ParticleMappings(final IdentifiersPair identifiersPair, final Mappings mappings) {
|
||||
super(identifiersPair, mappings);
|
||||
addBlockParticle("block");
|
||||
addBlockParticle("falling_dust");
|
||||
addBlockParticle("block_marker");
|
||||
|
||||
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.data.entity;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.util.KeyMappings;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
@@ -210,4 +211,8 @@ public interface EntityTracker {
|
||||
@Nullable DimensionData dimensionData(int dimensionId);
|
||||
|
||||
void setDimensions(Map<String, DimensionData> dimensions);
|
||||
|
||||
@Nullable KeyMappings registryKeys(String registryKey);
|
||||
|
||||
void addRegistryKeys(String registryKey, KeyMappings mappings);
|
||||
}
|
||||
@@ -31,8 +31,8 @@ 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
|
||||
* @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) {
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public interface EitherHolder<T> {
|
||||
/**
|
||||
* Returns an indirect holder via the resource key.
|
||||
*
|
||||
* @param key the resource key
|
||||
* @param key the resource key
|
||||
* @param <T> the type of the value
|
||||
* @return a new holder with the given resource key
|
||||
*/
|
||||
|
||||
@@ -27,7 +27,7 @@ import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.ToIntFunction;
|
||||
|
||||
/**
|
||||
* Set of ids that either holds a string tag key or an array of ids.
|
||||
@@ -56,19 +56,19 @@ public interface HolderSet {
|
||||
return new HolderSetImpl.Ids(ids);
|
||||
}
|
||||
|
||||
static HolderSet fromTag(final Tag tag, final Function<String, Integer> mappingFunction) {
|
||||
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.apply(stringTag.getValue());
|
||||
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.apply(value);
|
||||
ids[i] = mappingFunction.applyAsInt(value);
|
||||
}
|
||||
return HolderSet.of(ids);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.chunks;
|
||||
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
public interface DataPalette {
|
||||
|
||||
/**
|
||||
@@ -108,6 +110,21 @@ public interface DataPalette {
|
||||
*/
|
||||
void setPaletteIndexAt(int sectionCoordinate, int index);
|
||||
|
||||
/**
|
||||
* Replaces every id in the palette by applying the given mapper.
|
||||
*
|
||||
* @param mapper function from old id to new id
|
||||
*/
|
||||
default void replaceIds(IntUnaryOperator mapper) {
|
||||
for (int i = 0; i < this.size(); i++) {
|
||||
final int id = this.idByIndex(i);
|
||||
final int newId = mapper.applyAsInt(id);
|
||||
if (newId != id) {
|
||||
this.setIdByIndex(i, newId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new id to the palette.
|
||||
*
|
||||
@@ -121,7 +138,13 @@ public interface DataPalette {
|
||||
* @param oldId old id
|
||||
* @param newId new id
|
||||
*/
|
||||
void replaceId(int oldId, int newId);
|
||||
default void replaceId(int oldId, int newId) {
|
||||
for (int i = 0; i < this.size(); i++) {
|
||||
if (this.idByIndex(i) == oldId) {
|
||||
this.setIdByIndex(i, newId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the palette.
|
||||
|
||||
+71
-7
@@ -25,13 +25,13 @@ package com.viaversion.viaversion.api.minecraft.chunks;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
public final class DataPaletteImpl implements DataPalette {
|
||||
|
||||
private static final int DEFAULT_INITIAL_SIZE = 16;
|
||||
|
||||
private final IntList palette;
|
||||
private final IntArrayList palette;
|
||||
private final Int2IntMap inversePalette;
|
||||
private final int sizeBits;
|
||||
private ChunkData values;
|
||||
@@ -41,7 +41,7 @@ public final class DataPaletteImpl implements DataPalette {
|
||||
}
|
||||
|
||||
public DataPaletteImpl(final int valuesLength, final int initialSize) {
|
||||
values = new EmptyChunkData(valuesLength);
|
||||
values = new SingleChunkData(valuesLength);
|
||||
sizeBits = Integer.numberOfTrailingZeros(valuesLength) / 3;
|
||||
// Pre-size the palette array/map
|
||||
palette = new IntArrayList(initialSize);
|
||||
@@ -123,6 +123,53 @@ public final class DataPaletteImpl implements DataPalette {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceIds(final IntUnaryOperator mapper) {
|
||||
final int oldSize = palette.size();
|
||||
if (oldSize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
inversePalette.clear();
|
||||
int writeIndex = 0;
|
||||
int[] indexRemap = null;
|
||||
int firstCollision = 0;
|
||||
|
||||
final int[] palette = this.palette.elements();
|
||||
for (int readIndex = 0; readIndex < oldSize; readIndex++) {
|
||||
final int mappedId = mapper.applyAsInt(palette[readIndex]);
|
||||
final int existingIndex = inversePalette.putIfAbsent(mappedId, writeIndex);
|
||||
if (existingIndex == -1) {
|
||||
palette[writeIndex] = mappedId;
|
||||
if (indexRemap != null) {
|
||||
indexRemap[readIndex - firstCollision] = writeIndex;
|
||||
}
|
||||
writeIndex++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The mapped value already exists in the palette. The original index will be removed at the end
|
||||
if (indexRemap == null) {
|
||||
indexRemap = new int[oldSize - readIndex];
|
||||
firstCollision = readIndex;
|
||||
}
|
||||
indexRemap[readIndex - firstCollision] = existingIndex;
|
||||
}
|
||||
|
||||
// If any mapped ids were already present (writeIndex < oldSize),
|
||||
// collapse the entries and set values to their shifted palette indexes
|
||||
if (indexRemap != null) {
|
||||
this.palette.removeElements(writeIndex, oldSize);
|
||||
final int len = values.size();
|
||||
for (int i = 0; i < len; i++) {
|
||||
final int oldIndex = values.get(i);
|
||||
if (oldIndex >= firstCollision) {
|
||||
values.set(i, indexRemap[oldIndex - firstCollision]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addId(final int id) {
|
||||
inversePalette.put(id, palette.size());
|
||||
@@ -139,13 +186,15 @@ public final class DataPaletteImpl implements DataPalette {
|
||||
int get(int idx);
|
||||
|
||||
void set(int idx, int val);
|
||||
|
||||
int size();
|
||||
}
|
||||
|
||||
private class EmptyChunkData implements ChunkData {
|
||||
private final class SingleChunkData implements ChunkData {
|
||||
|
||||
private final int size;
|
||||
|
||||
public EmptyChunkData(int size) {
|
||||
public SingleChunkData(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@@ -161,9 +210,14 @@ public final class DataPaletteImpl implements DataPalette {
|
||||
values.set(idx, val);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
private class ByteChunkData implements ChunkData {
|
||||
private final class ByteChunkData implements ChunkData {
|
||||
private final byte[] data;
|
||||
|
||||
public ByteChunkData(int size) {
|
||||
@@ -185,9 +239,14 @@ public final class DataPaletteImpl implements DataPalette {
|
||||
}
|
||||
data[idx] = (byte) val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return data.length;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ShortChunkData implements ChunkData {
|
||||
private static final class ShortChunkData implements ChunkData {
|
||||
private final short[] data;
|
||||
|
||||
public ShortChunkData(byte[] data) {
|
||||
@@ -206,6 +265,11 @@ public final class DataPaletteImpl implements DataPalette {
|
||||
public void set(int idx, int val) {
|
||||
data[idx] = (short) val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return data.length;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.codec;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
@@ -35,8 +36,12 @@ public interface CodecContext {
|
||||
|
||||
boolean isSupported(StructuredDataKey<?> key);
|
||||
|
||||
UserConnection connection();
|
||||
|
||||
interface RegistryAccess {
|
||||
|
||||
UserConnection connection();
|
||||
|
||||
Key item(int id);
|
||||
|
||||
Key attributeModifier(int id);
|
||||
@@ -53,7 +58,7 @@ public interface CodecContext {
|
||||
* Returns the key for a stored mapping type and its numeric id.
|
||||
*
|
||||
* @param mappingType mapping type
|
||||
* @param id numeric id
|
||||
* @param id numeric id
|
||||
* @return the key
|
||||
*/
|
||||
Key key(MappingData.MappingType mappingType, int id);
|
||||
@@ -62,20 +67,20 @@ public interface CodecContext {
|
||||
* Returns the numeric id for a stored mapping type and its identifier.
|
||||
*
|
||||
* @param mappingType mapping type
|
||||
* @param identifier identifier
|
||||
* @param identifier identifier
|
||||
* @return the numeric id, or -1 if not found
|
||||
*/
|
||||
int id(MappingData.MappingType mappingType, String identifier);
|
||||
|
||||
static RegistryAccess of(final Protocol<?, ?, ?, ?> protocol) {
|
||||
return new RegistryAccessImpl(protocol);
|
||||
static RegistryAccess of(final Protocol<?, ?, ?, ?> protocol, final UserConnection connection) {
|
||||
return new RegistryAccessImpl(protocol, connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for a client-synchronized registry element.
|
||||
*
|
||||
* @param registry registry key
|
||||
* @param id numeric id
|
||||
* @param id numeric id
|
||||
* @return the key
|
||||
*/
|
||||
Key registryKey(String registry, int id);
|
||||
|
||||
@@ -81,12 +81,12 @@ public interface Ops {
|
||||
/**
|
||||
* Writes the given value or default value if the value is null.
|
||||
*
|
||||
* @param key map key
|
||||
* @param type type of the value
|
||||
* @param key map key
|
||||
* @param type type of the value
|
||||
* @param value the value to write, or null
|
||||
* @param def default value to write if the value is null
|
||||
* @param def default value to write if the value is null
|
||||
* @param <V> value type
|
||||
* @return self
|
||||
* @param <V> value type
|
||||
*/
|
||||
default <V> MapSerializer write(final String key, final Type<V> type, @Nullable final V value, final V def) {
|
||||
write(Types.STRING, key, type, value != null ? value : def);
|
||||
@@ -96,11 +96,11 @@ public interface Ops {
|
||||
/**
|
||||
* Writes the given value if it is not null.
|
||||
*
|
||||
* @param key map key
|
||||
* @param type type of the value
|
||||
* @param key map key
|
||||
* @param type type of the value
|
||||
* @param value the value to write, or null
|
||||
* @param <V> value type
|
||||
* @return self
|
||||
* @param <V> value type
|
||||
*/
|
||||
default <V> MapSerializer writeOptional(final String key, final Type<V> type, @Nullable final V value) {
|
||||
if (value != null) {
|
||||
@@ -112,12 +112,12 @@ public interface Ops {
|
||||
/**
|
||||
* Writes the given value if it is not null and not equal to the default value.
|
||||
*
|
||||
* @param key map key
|
||||
* @param type type of the value
|
||||
* @param key map key
|
||||
* @param type type of the value
|
||||
* @param value the value to write, or null
|
||||
* @param def default value to compare against
|
||||
* @param def default value to compare against
|
||||
* @param <V> value type
|
||||
* @return self
|
||||
* @param <V> value type
|
||||
*/
|
||||
default <V> MapSerializer writeOptional(final String key, final Type<V> type, @Nullable final V value, final V def) {
|
||||
if (value != null && !Objects.deepEquals(value, def)) {
|
||||
|
||||
+19
-10
@@ -23,31 +23,40 @@
|
||||
package com.viaversion.viaversion.api.minecraft.codec;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.FullMappings;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.data.entity.EntityTracker;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.rewriter.RegistryDataRewriter;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.KeyMappings;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
final class RegistryAccessImpl implements CodecContext.RegistryAccess {
|
||||
private final RegistryDataRewriter registryDataRewriter;
|
||||
private final EntityTracker entityTracker;
|
||||
private final MappingData mappingData;
|
||||
private final UserConnection connection;
|
||||
private final boolean mapped;
|
||||
|
||||
RegistryAccessImpl(final Protocol<?, ?, ?, ?> protocol) {
|
||||
this.mappingData = protocol.getMappingData();
|
||||
this.registryDataRewriter = protocol.getRegistryDataRewriter();
|
||||
RegistryAccessImpl(final Protocol<?, ?, ?, ?> protocol, final UserConnection connection) {
|
||||
this.mappingData = Preconditions.checkNotNull(protocol.getMappingData());
|
||||
this.entityTracker = Preconditions.checkNotNull(protocol.getEntityRewriter().tracker(connection));
|
||||
this.connection = connection;
|
||||
this.mapped = false;
|
||||
}
|
||||
|
||||
private RegistryAccessImpl(final MappingData mappingData, final RegistryDataRewriter registryDataRewriter, final boolean mapped) {
|
||||
private RegistryAccessImpl(final MappingData mappingData, final UserConnection connection, final EntityTracker entityTracker, final boolean mapped) {
|
||||
this.mappingData = mappingData;
|
||||
this.registryDataRewriter = registryDataRewriter;
|
||||
this.connection = connection;
|
||||
this.entityTracker = entityTracker;
|
||||
this.mapped = mapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConnection connection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key item(final int id) {
|
||||
return key(mappingData.getFullItemMappings(), id);
|
||||
@@ -91,8 +100,8 @@ final class RegistryAccessImpl implements CodecContext.RegistryAccess {
|
||||
|
||||
@Override
|
||||
public Key registryKey(final String registry, final int id) {
|
||||
final KeyMappings mappings = registryDataRewriter.getMappings(registry);
|
||||
Preconditions.checkNotNull(mappings, "No registry mappings for registry: " + registry);
|
||||
final KeyMappings mappings = entityTracker.registryKeys(registry);
|
||||
Preconditions.checkNotNull(mappings, "No registry mappings for registry: %s", registry);
|
||||
final String identifier = id >= 0 && id < mappings.size() ? mappings.idToKey(id) : null;
|
||||
return key(identifier, id);
|
||||
}
|
||||
@@ -108,6 +117,6 @@ final class RegistryAccessImpl implements CodecContext.RegistryAccess {
|
||||
|
||||
@Override
|
||||
public CodecContext.RegistryAccess withMapped(final boolean mapped) {
|
||||
return this.mapped == mapped ? this : new RegistryAccessImpl(this.mappingData, this.registryDataRewriter, mapped);
|
||||
return this.mapped == mapped ? this : new RegistryAccessImpl(this.mappingData, this.connection, this.entityTracker, mapped);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -145,13 +145,13 @@ public enum EntityTypes1_14 implements EntityType {
|
||||
SHEEP(ABSTRACT_ANIMAL),
|
||||
TURTLE(ABSTRACT_ANIMAL),
|
||||
FOX(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -146,13 +146,13 @@ public enum EntityTypes1_15 implements EntityType {
|
||||
BEE(ABSTRACT_ANIMAL),
|
||||
TURTLE(ABSTRACT_ANIMAL),
|
||||
FOX(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -148,13 +148,13 @@ public enum EntityTypes1_16 implements EntityType {
|
||||
FOX(ABSTRACT_ANIMAL),
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -148,13 +148,13 @@ public enum EntityTypes1_16_2 implements EntityType {
|
||||
FOX(ABSTRACT_ANIMAL),
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -154,13 +154,13 @@ public enum EntityTypes1_17 implements EntityType {
|
||||
GOAT(ABSTRACT_ANIMAL),
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -158,13 +158,13 @@ public enum EntityTypes1_19 implements EntityType {
|
||||
GOAT(ABSTRACT_ANIMAL),
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -158,13 +158,13 @@ public enum EntityTypes1_19_3 implements EntityType {
|
||||
GOAT(ABSTRACT_ANIMAL),
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -165,13 +165,13 @@ public enum EntityTypes1_19_4 implements EntityType {
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -166,13 +166,13 @@ public enum EntityTypes1_20_3 implements EntityType {
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -171,13 +171,13 @@ public enum EntityTypes1_20_5 implements EntityType {
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -185,6 +185,7 @@ public enum EntityTypes1_21_11 implements EntityType {
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
HAPPY_GHAST(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
|
||||
COW(ABSTRACT_COW),
|
||||
@@ -192,7 +193,6 @@ public enum EntityTypes1_21_11 implements EntityType {
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -176,13 +176,13 @@ public enum EntityTypes1_21_2 implements EntityType {
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -176,13 +176,13 @@ public enum EntityTypes1_21_4 implements EntityType {
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -179,6 +179,7 @@ public enum EntityTypes1_21_5 implements EntityType {
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
|
||||
COW(ABSTRACT_COW),
|
||||
@@ -186,7 +187,6 @@ public enum EntityTypes1_21_5 implements EntityType {
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -180,6 +180,7 @@ public enum EntityTypes1_21_6 implements EntityType {
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
HAPPY_GHAST(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
|
||||
COW(ABSTRACT_COW),
|
||||
@@ -187,7 +188,6 @@ public enum EntityTypes1_21_6 implements EntityType {
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+1
-1
@@ -185,6 +185,7 @@ public enum EntityTypes1_21_9 implements EntityType {
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
HAPPY_GHAST(ABSTRACT_ANIMAL),
|
||||
OCELOT(ABSTRACT_ANIMAL),
|
||||
|
||||
ABSTRACT_COW(ABSTRACT_ANIMAL, null),
|
||||
COW(ABSTRACT_COW),
|
||||
@@ -192,7 +193,6 @@ public enum EntityTypes1_21_9 implements EntityType {
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
|
||||
+4
@@ -43,6 +43,10 @@ public abstract class AbstractEntityDataTypes implements EntityDataTypes {
|
||||
return values;
|
||||
}
|
||||
|
||||
public Class<? extends EntityDataType> getDataTypeClass() {
|
||||
return byId(0).getClass();
|
||||
}
|
||||
|
||||
protected EntityDataType add(final int typeId, final Type<?> type) {
|
||||
if (values[typeId] != null) {
|
||||
throw new IllegalArgumentException("Entity data type ID " + typeId + " is already registered as " + values[typeId]);
|
||||
|
||||
+27
-1
@@ -37,6 +37,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) implements Copyable, Rewritable {
|
||||
|
||||
@@ -226,7 +227,7 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
|
||||
}
|
||||
|
||||
public static class Display implements Copyable {
|
||||
public static final String[] DISPLAY_TYPES = {"default", "hidden", "override_text"};
|
||||
public static final String[] DISPLAY_TYPES = {"default", "hidden", "override"};
|
||||
public static final Display DEFAULT = new Display(0);
|
||||
private final int id;
|
||||
|
||||
@@ -246,6 +247,17 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
|
||||
public Display copy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (!(o instanceof final Display display)) return false;
|
||||
return id == display.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class OverrideText extends Display {
|
||||
@@ -271,5 +283,19 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
|
||||
public OverrideText copy() {
|
||||
return new OverrideText(this.component.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (!(o instanceof final OverrideText that)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
return Objects.equals(component, that.component);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + Objects.hashCode(component);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -122,7 +122,7 @@ public record BlocksAttacks(
|
||||
.writeOptional("disable_cooldown_scale", Types.FLOAT, value.disableCooldownScale(), 1F)
|
||||
.writeOptional("damage_reductions", DamageReduction.ARRAY_TYPE, value.damageReductions(), defaultDamageReductions)
|
||||
.writeOptional("item_damage", ItemDamageFunction.TYPE, value.itemDamage(), defaultItemDamage)
|
||||
.writeOptional("bypassed_by", Types.HOLDER_SET, value.bypassedBy())
|
||||
.writeOptional("bypassed_by", new HolderSetType(RegistryKey.of("damage_type")), value.bypassedBy())
|
||||
.writeOptional("block_sound", Types.SOUND_EVENT, value.blockSound())
|
||||
.writeOptional("disabled_sound", Types.SOUND_EVENT, value.disableSound()));
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ public interface ViaPlatform<T> {
|
||||
/**
|
||||
* Modify the server details payload before it is sent.
|
||||
* This method allows adding, changing, or removing fields from the payload.
|
||||
* It is only called if {@link ViaVersionConfig#sendPlayerDetails()} is true.
|
||||
* It is only called if {@link ViaVersionConfig#sendServerDetails()} is true.
|
||||
*
|
||||
* @param connection The UserConnection
|
||||
* @param payload The constructed payload to modify
|
||||
|
||||
@@ -1,36 +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.protocol;
|
||||
|
||||
/**
|
||||
* A simple protocol which does not have any packet types.
|
||||
* <p>
|
||||
* {@link AbstractProtocol} should be preferred over this class in most cases.
|
||||
*/
|
||||
public abstract class AbstractSimpleProtocol extends AbstractProtocol<SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes,
|
||||
SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes> implements SimpleProtocol {
|
||||
|
||||
protected AbstractSimpleProtocol() {
|
||||
super(null, null, null, null);
|
||||
}
|
||||
}
|
||||
@@ -68,10 +68,6 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
|
||||
registerServerbound(state, packetType.getId(), packetType.getId(), handler, false);
|
||||
}
|
||||
|
||||
default void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
|
||||
registerServerbound(state, unmappedPacketId, mappedPacketId, handler, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a serverbound packet, with id transformation and remapper.
|
||||
*
|
||||
@@ -79,19 +75,17 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
|
||||
* @param unmappedPacketId unmapped packet id
|
||||
* @param mappedPacketId mapped packet id
|
||||
* @param handler packet handler
|
||||
* @param override whether an existing mapper should be overridden
|
||||
* @see #registerServerbound(ServerboundPacketType, ServerboundPacketType, PacketHandler, boolean)
|
||||
*/
|
||||
default void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
|
||||
registerServerbound(state, unmappedPacketId, mappedPacketId, handler, false);
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
void registerServerbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler, boolean override);
|
||||
|
||||
void cancelServerbound(State state, int mappedPacketId);
|
||||
|
||||
default void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
|
||||
registerClientbound(state, unmappedPacketId, mappedPacketId, handler, false);
|
||||
}
|
||||
|
||||
void cancelClientbound(State state, int unmappedPacketId);
|
||||
|
||||
/**
|
||||
* Registers a clientbound packet, with id transformation and remapper.
|
||||
*
|
||||
@@ -99,9 +93,15 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
|
||||
* @param unmappedPacketId unmapped packet id
|
||||
* @param mappedPacketId mapped packet id
|
||||
* @param handler packet handler
|
||||
* @param override whether an existing mapper should be overridden
|
||||
* @see #registerClientbound(ClientboundPacketType, ClientboundPacketType, PacketHandler, boolean)
|
||||
*/
|
||||
default void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler) {
|
||||
registerClientbound(state, unmappedPacketId, mappedPacketId, handler, false);
|
||||
}
|
||||
|
||||
void cancelClientbound(State state, int unmappedPacketId);
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
void registerClientbound(State state, int unmappedPacketId, int mappedPacketId, @Nullable PacketHandler handler, boolean override);
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
@@ -144,6 +144,7 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
|
||||
* @param handler packet handler
|
||||
* @param override whether an existing mapping should be overridden if present
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
void registerClientbound(CU packetType, @Nullable CM mappedPacketType, @Nullable PacketHandler handler, boolean override);
|
||||
|
||||
/**
|
||||
@@ -191,6 +192,7 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
|
||||
* @param handler packet handler
|
||||
* @param override whether an existing mapping should be overridden if present
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
void registerServerbound(SU packetType, @Nullable SM mappedPacketType, @Nullable PacketHandler handler, boolean override);
|
||||
|
||||
/**
|
||||
@@ -260,6 +262,22 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
|
||||
*/
|
||||
void appendServerbound(SU type, PacketHandler handler);
|
||||
|
||||
/**
|
||||
* Replaces a clientbound packet type handler with another.
|
||||
*
|
||||
* @param type clientbound packet type
|
||||
* @param handler packet handler
|
||||
*/
|
||||
void replaceClientbound(CU type, @Nullable PacketHandler handler);
|
||||
|
||||
/**
|
||||
* Replaces a serverbound packet type handler with another.
|
||||
*
|
||||
* @param type serverbound packet type
|
||||
* @param handler packet handler
|
||||
*/
|
||||
void replaceServerbound(SU type, @Nullable PacketHandler handler);
|
||||
|
||||
/**
|
||||
* Transform a packet using this protocol
|
||||
*
|
||||
@@ -441,4 +459,13 @@ public interface Protocol<CU extends ClientboundPacketType, CM extends Clientbou
|
||||
default boolean isBaseProtocol() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this protocol as dependent on another. Before being initialized, it will wait for the dependency's completion.
|
||||
*
|
||||
* @return protocol class to depend on
|
||||
*/
|
||||
default @Nullable Class<? extends Protocol<?, ?, ?, ?>> dependsOn() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -249,7 +249,17 @@ public interface ProtocolManager {
|
||||
*
|
||||
* @return true if the executor has now been shut down
|
||||
*/
|
||||
boolean checkForMappingCompletion();
|
||||
default boolean checkForMappingCompletion() {
|
||||
return checkForMappingCompletion(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the executor and uncaches mappings if all futures have been completed.
|
||||
*
|
||||
* @param propagateErrors whether to propagate errors from the futures to the caller
|
||||
* @return true if the executor has now been shut down
|
||||
*/
|
||||
boolean checkForMappingCompletion(boolean propagateErrors);
|
||||
|
||||
/**
|
||||
* Executes the given runnable asynchronously, adding a {@link CompletableFuture}
|
||||
|
||||
+5
@@ -50,6 +50,11 @@ final class PacketIdMapping implements PacketMapping {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHandler(@Nullable final PacketHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PacketHandler handler() {
|
||||
return handler;
|
||||
|
||||
+7
@@ -39,6 +39,13 @@ public interface PacketMapping {
|
||||
*/
|
||||
void applyType(PacketWrapper wrapper);
|
||||
|
||||
/**
|
||||
* Replaces the current packet handler.
|
||||
*
|
||||
* @param handler packet transformer
|
||||
*/
|
||||
void setHandler(@Nullable PacketHandler handler);
|
||||
|
||||
/**
|
||||
* Returns a packet transformer to transform a packet from one protocol version to another.
|
||||
*
|
||||
|
||||
+5
@@ -52,6 +52,11 @@ final class PacketTypeMapping implements PacketMapping {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHandler(@Nullable final PacketHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable PacketHandler handler() {
|
||||
return handler;
|
||||
|
||||
+5
@@ -74,6 +74,11 @@ public interface PacketTypesProvider<CU extends ClientboundPacketType, CM extend
|
||||
return map != null ? map.typeByName(typeName) : null;
|
||||
}
|
||||
|
||||
default @Nullable CM mappedClientboundType(final State state, final String typeName) {
|
||||
PacketTypeMap<CM> map = mappedClientboundPacketTypes().get(state);
|
||||
return map != null ? map.typeByName(typeName) : null;
|
||||
}
|
||||
|
||||
default @Nullable SU unmappedServerboundType(final State state, final String typeName) {
|
||||
PacketTypeMap<SU> map = unmappedServerboundPacketTypes().get(state);
|
||||
return map != null ? map.typeByName(typeName) : null;
|
||||
|
||||
+1
-1
@@ -93,7 +93,7 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||
public static final ProtocolVersion v1_21_7 = register(772, "1.21.7-1.21.8", new SubVersionRange("1.21", 7, 8));
|
||||
public static final ProtocolVersion v1_21_9 = register(773, "1.21.9-1.21.10", new SubVersionRange("1.21", 9, 10));
|
||||
public static final ProtocolVersion v1_21_11 = register(774, "1.21.11");
|
||||
public static final ProtocolVersion v26_1 = register(775, "26.1");
|
||||
public static final ProtocolVersion v26_1 = register(775, "26.1-26.1.2", new SubVersionRange("26.1", 0, 2));
|
||||
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
|
||||
|
||||
static {
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.google.gson.JsonElement;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public interface ComponentRewriter {
|
||||
@@ -37,4 +38,6 @@ public interface ComponentRewriter {
|
||||
JsonElement processText(UserConnection connection, @Nullable String json);
|
||||
|
||||
void handleShowItem(UserConnection connection, CompoundTag itemTag);
|
||||
|
||||
void passthroughAndProcess(PacketWrapper wrapper);
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import java.util.List;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter<T> {
|
||||
|
||||
@@ -39,6 +40,8 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
|
||||
*/
|
||||
EntityType typeFromId(int type);
|
||||
|
||||
@Nullable EntityType typeFromId(String type);
|
||||
|
||||
/**
|
||||
* Returns the entity type from the given id.
|
||||
* From 1.14 and onwards, this is the same exact value as {@link #typeFromId(int)}.
|
||||
@@ -70,9 +73,9 @@ public interface EntityRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter
|
||||
/**
|
||||
* Handles and transforms entity data of an entity.
|
||||
*
|
||||
* @param entityId entity id
|
||||
* @param dataList full, mutable list of entity data
|
||||
* @param connection user connection
|
||||
* @param entityId entity id
|
||||
* @param dataList full, mutable list of entity data
|
||||
* @param connection user connection
|
||||
*/
|
||||
void handleEntityData(int entityId, List<EntityData> dataList, UserConnection connection);
|
||||
|
||||
|
||||
@@ -24,15 +24,23 @@ package com.viaversion.viaversion.api.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.util.KeyMappings;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
|
||||
public interface RegistryDataRewriter {
|
||||
|
||||
@Nullable
|
||||
KeyMappings getMappings(String registryKey);
|
||||
void handle(PacketWrapper wrapper);
|
||||
|
||||
boolean shouldRemoveRegistry(String registryKey);
|
||||
|
||||
boolean hasRegistriesToRemove();
|
||||
|
||||
void updateDialog(UserConnection connection, CompoundTag tag);
|
||||
|
||||
/**
|
||||
* Sends registries that had additional entries configured, but weren't sent by the server at all
|
||||
* by the time finish_configuration was sent to the client.
|
||||
*
|
||||
* @param connection the user connection
|
||||
*/
|
||||
void sendMissingRegistries(final UserConnection connection);
|
||||
}
|
||||
@@ -26,10 +26,10 @@ import com.viaversion.viaversion.api.minecraft.codec.Ops;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public abstract class OptionalType<T> extends Type<T> {
|
||||
public class OptionalType<T> extends Type<T> {
|
||||
private final Type<T> type;
|
||||
|
||||
protected OptionalType(final Type<T> type) {
|
||||
public OptionalType(final Type<T> type) {
|
||||
super(type.getOutputClass());
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
+2
-2
@@ -40,7 +40,7 @@ public class BlockEntityType1_20_2 extends Type<BlockEntity> {
|
||||
final byte xz = buffer.readByte();
|
||||
final short y = buffer.readShort();
|
||||
final int typeId = Types.VAR_INT.readPrimitive(buffer);
|
||||
final CompoundTag tag = Types.COMPOUND_TAG.read(buffer);
|
||||
final CompoundTag tag = Types.TRUSTED_COMPOUND_TAG.read(buffer);
|
||||
return new BlockEntityImpl(xz, y, typeId, tag);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,6 @@ public class BlockEntityType1_20_2 extends Type<BlockEntity> {
|
||||
buffer.writeByte(entity.packedXZ());
|
||||
buffer.writeShort(entity.y());
|
||||
Types.VAR_INT.writePrimitive(buffer, entity.typeId());
|
||||
Types.COMPOUND_TAG.write(buffer, entity.tag());
|
||||
Types.TRUSTED_COMPOUND_TAG.write(buffer, entity.tag());
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.misc;
|
||||
|
||||
import com.viaversion.nbt.limiter.TagLimiter;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.minecraft.codec.Ops;
|
||||
@@ -49,7 +50,7 @@ public class CompoundTagType extends Type<CompoundTag> {
|
||||
|
||||
public CompoundTagType(final boolean limitMaxBytes) {
|
||||
super(CompoundTag.class);
|
||||
this.maxBytes = limitMaxBytes ? NamedCompoundTagType.MAX_NBT_BYTES : Integer.MAX_VALUE;
|
||||
this.maxBytes = limitMaxBytes ? TagLimiter.DEFAULT_MAX_BYTES : Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+6
-9
@@ -28,17 +28,14 @@ import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.type.OptionalType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.io.FastByteBufInputStream;
|
||||
import com.viaversion.viaversion.io.FastByteBufOutputStream;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import java.io.IOException;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class NamedCompoundTagType extends Type<CompoundTag> {
|
||||
|
||||
public static final int MAX_NBT_BYTES = 2097152; // 2mb
|
||||
public static final int MAX_NESTING_LEVEL = 512;
|
||||
|
||||
public NamedCompoundTagType() {
|
||||
super(CompoundTag.class);
|
||||
}
|
||||
@@ -46,7 +43,7 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
|
||||
@Override
|
||||
public CompoundTag read(final ByteBuf buffer) {
|
||||
try {
|
||||
return read(buffer, MAX_NBT_BYTES, true);
|
||||
return read(buffer, TagLimiter.DEFAULT_MAX_BYTES, true);
|
||||
} catch (final IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -74,8 +71,8 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
|
||||
buffer.skipBytes(buffer.readUnsignedShort());
|
||||
}
|
||||
|
||||
final TagLimiter tagLimiter = TagLimiter.create(maxBytes, MAX_NESTING_LEVEL);
|
||||
return CompoundTag.read(new ByteBufInputStream(buffer), tagLimiter, 0);
|
||||
final TagLimiter tagLimiter = TagLimiter.create(maxBytes, TagLimiter.DEFAULT_MAX_NESTING_LEVEL);
|
||||
return CompoundTag.read(new FastByteBufInputStream(buffer), tagLimiter, 0);
|
||||
}
|
||||
|
||||
public static void write(final ByteBuf buffer, final Tag tag, final @Nullable String name) throws IOException {
|
||||
@@ -84,7 +81,7 @@ public class NamedCompoundTagType extends Type<CompoundTag> {
|
||||
return;
|
||||
}
|
||||
|
||||
final ByteBufOutputStream out = new ByteBufOutputStream(buffer);
|
||||
final FastByteBufOutputStream out = new FastByteBufOutputStream(buffer);
|
||||
out.writeByte(tag.getTagId());
|
||||
if (name != null) {
|
||||
out.writeUTF(name);
|
||||
|
||||
@@ -59,17 +59,13 @@ public class ParticleType extends DynamicType<Particle> {
|
||||
return protocol.getMappingData().getParticleMappings();
|
||||
}
|
||||
|
||||
public static DataReader<Particle> itemHandler(final Type<Item> itemType) {
|
||||
return (buf, particle) -> particle.add(itemType, itemType.read(buf));
|
||||
}
|
||||
|
||||
public static final class Readers {
|
||||
|
||||
public static final DataReader<Particle> BLOCK = (buf, particle) -> {
|
||||
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Flat Block
|
||||
};
|
||||
public static final DataReader<Particle> ITEM1_13 = itemHandler(Types.ITEM1_13);
|
||||
public static final DataReader<Particle> ITEM1_13_2 = itemHandler(Types.ITEM1_13_2);
|
||||
public static final DataReader<Particle> ITEM1_13 = item(Types.ITEM1_13);
|
||||
public static final DataReader<Particle> ITEM1_13_2 = item(Types.ITEM1_13_2);
|
||||
public static final DataReader<Particle> DUST = (buf, particle) -> {
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Red 0-1
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Green 0-1
|
||||
@@ -172,4 +168,103 @@ public class ParticleType extends DynamicType<Particle> {
|
||||
return (buf, particle) -> particle.add(item, item.read(buf));
|
||||
}
|
||||
}
|
||||
|
||||
public static final class Fillers {
|
||||
|
||||
public static DynamicType<Particle>.DataFiller fill1_13_2(final Protocol<?, ?, ?, ?> protocol, final ParticleType type, final boolean useMappedNames) {
|
||||
return type.filler(protocol, useMappedNames)
|
||||
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
|
||||
.reader("block", Readers.BLOCK)
|
||||
.reader("dust", Readers.DUST)
|
||||
.reader("falling_dust", Readers.BLOCK);
|
||||
}
|
||||
|
||||
public static DataFiller fill1_17(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
|
||||
return fill1_13_2(protocol, type, true)
|
||||
.reader("dust_color_transition", Readers.DUST_TRANSITION)
|
||||
.reader("vibration", Readers.VIBRATION);
|
||||
}
|
||||
|
||||
public static void fill1_18(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
|
||||
fill1_17(protocol, type).reader("block_marker", Readers.BLOCK);
|
||||
}
|
||||
|
||||
public static void fill1_19(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
|
||||
type.filler(protocol)
|
||||
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
|
||||
.reader("block", Readers.BLOCK)
|
||||
.reader("block_marker", Readers.BLOCK)
|
||||
.reader("dust", Readers.DUST)
|
||||
.reader("falling_dust", Readers.BLOCK)
|
||||
.reader("dust_color_transition", Readers.DUST_TRANSITION)
|
||||
.reader("vibration", Readers.VIBRATION1_19)
|
||||
.reader("sculk_charge", Readers.SCULK_CHARGE)
|
||||
.reader("shriek", Readers.SHRIEK);
|
||||
}
|
||||
|
||||
public static DataFiller fill1_20_3(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
|
||||
return type.filler(protocol)
|
||||
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
|
||||
.reader("block", Readers.BLOCK)
|
||||
.reader("block_marker", Readers.BLOCK)
|
||||
.reader("dust", Readers.DUST)
|
||||
.reader("falling_dust", Readers.BLOCK)
|
||||
.reader("dust_color_transition", Readers.DUST_TRANSITION)
|
||||
.reader("vibration", Readers.VIBRATION1_20_3)
|
||||
.reader("sculk_charge", Readers.SCULK_CHARGE)
|
||||
.reader("shriek", Readers.SHRIEK);
|
||||
}
|
||||
|
||||
public static void fill1_20_5(final Protocol<?, ?, ?, ?> protocol, final ParticleType type) {
|
||||
fill1_20_3(protocol, type)
|
||||
.reader("dust_pillar", Readers.BLOCK)
|
||||
.reader("entity_effect", Readers.COLOR);
|
||||
}
|
||||
|
||||
public static void fill1_21_2(final Protocol<?, ?, ?, ?> protocol) {
|
||||
protocol.mappedTypes().particle().filler(protocol)
|
||||
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemType()))
|
||||
.reader("block", Readers.BLOCK)
|
||||
.reader("block_marker", Readers.BLOCK)
|
||||
.reader("dust_pillar", Readers.BLOCK)
|
||||
.reader("falling_dust", Readers.BLOCK)
|
||||
.reader("block_crumble", Readers.BLOCK)
|
||||
.reader("dust", Readers.DUST1_21_2)
|
||||
.reader("dust_color_transition", Readers.DUST_TRANSITION1_21_2)
|
||||
.reader("vibration", Readers.VIBRATION1_20_3)
|
||||
.reader("sculk_charge", Readers.SCULK_CHARGE)
|
||||
.reader("shriek", Readers.SHRIEK)
|
||||
.reader("entity_effect", Readers.COLOR)
|
||||
.reader("trail", Readers.TRAIL1_21_2);
|
||||
}
|
||||
|
||||
public static DataFiller fill1_21_4(final Protocol<?, ?, ?, ?> protocol) {
|
||||
return protocol.mappedTypes().particle().filler(protocol)
|
||||
.reader("item", Readers.item(protocol.getItemRewriter().mappedItemTemplateType()))
|
||||
.reader("block", Readers.BLOCK)
|
||||
.reader("block_marker", Readers.BLOCK)
|
||||
.reader("dust_pillar", Readers.BLOCK)
|
||||
.reader("falling_dust", Readers.BLOCK)
|
||||
.reader("block_crumble", Readers.BLOCK)
|
||||
.reader("dust", Readers.DUST1_21_2)
|
||||
.reader("dust_color_transition", Readers.DUST_TRANSITION1_21_2)
|
||||
.reader("vibration", Readers.VIBRATION1_20_3)
|
||||
.reader("sculk_charge", Readers.SCULK_CHARGE)
|
||||
.reader("shriek", Readers.SHRIEK)
|
||||
.reader("entity_effect", Readers.COLOR)
|
||||
.reader("trail", Readers.TRAIL1_21_4);
|
||||
}
|
||||
|
||||
public static DataFiller fill1_21_5(final Protocol<?, ?, ?, ?> protocol) {
|
||||
return fill1_21_4(protocol).reader("tinted_leaves", Readers.COLOR);
|
||||
}
|
||||
|
||||
public static void fill1_21_9(final Protocol<?, ?, ?, ?> protocol) {
|
||||
fill1_21_5(protocol)
|
||||
.reader("dragon_breath", Readers.POWER)
|
||||
.reader("effect", Readers.SPELL)
|
||||
.reader("instant_effect", Readers.SPELL)
|
||||
.reader("flash", Readers.COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,8 +43,8 @@ import com.viaversion.viaversion.api.minecraft.codec.Ops;
|
||||
import com.viaversion.viaversion.api.type.OptionalType;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.io.FastByteBufInputStream;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -58,7 +58,7 @@ public class TagType extends Type<Tag> {
|
||||
|
||||
public TagType(final boolean limitBytes) {
|
||||
super(Tag.class);
|
||||
this.maxBytes = limitBytes ? NamedCompoundTagType.MAX_NBT_BYTES : Integer.MAX_VALUE;
|
||||
this.maxBytes = limitBytes ? TagLimiter.DEFAULT_MAX_BYTES : Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,9 +68,9 @@ public class TagType extends Type<Tag> {
|
||||
return null;
|
||||
}
|
||||
|
||||
final TagLimiter tagLimiter = TagLimiter.create(this.maxBytes, NamedCompoundTagType.MAX_NESTING_LEVEL);
|
||||
final TagLimiter tagLimiter = TagLimiter.create(this.maxBytes, TagLimiter.DEFAULT_MAX_NESTING_LEVEL);
|
||||
try {
|
||||
return TagRegistry.read(id, new ByteBufInputStream(buffer), tagLimiter, 0);
|
||||
return TagRegistry.read(id, new FastByteBufInputStream(buffer), tagLimiter, 0);
|
||||
} catch (final IOException e) {
|
||||
if (Via.getManager().isDebug()) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
@@ -60,7 +60,7 @@ public class InformativeException extends RuntimeException {
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
final StringBuilder builder = new StringBuilder("Please report this on the Via support Discord or open an issue on the relevant GitHub repository\n");
|
||||
final StringBuilder builder = new StringBuilder("Please report the full error (!) from the console on the Via support Discord or open an issue on the relevant GitHub repository.\n");
|
||||
boolean first = true;
|
||||
for (final DataEntry entry : dataEntries) {
|
||||
if (!first) {
|
||||
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* 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.io;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UTFDataFormatException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* {@link ByteBufInputStream} alternative with a more fine-tuned {@link #readUTF()} implementation
|
||||
* for fast reading of NBT strings.
|
||||
*/
|
||||
public final class FastByteBufInputStream extends InputStream implements DataInput {
|
||||
|
||||
private static final byte[] EMPTY_BYTES = new byte[0];
|
||||
private static final char[] EMPTY_CHARS = new char[0];
|
||||
private byte[] bytearr = EMPTY_BYTES;
|
||||
private char[] chararr = EMPTY_CHARS;
|
||||
private final ByteBuf buf;
|
||||
|
||||
public FastByteBufInputStream(final ByteBuf buffer) {
|
||||
Preconditions.checkNotNull(buffer);
|
||||
this.buf = buffer;
|
||||
buffer.markReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readUTF() throws IOException {
|
||||
// Note that this is a modified UTF-8 format, so we can't use netty's string reading
|
||||
final int utflen = readUnsignedShort();
|
||||
if (utflen == 0) {
|
||||
return "";
|
||||
}
|
||||
|
||||
final ByteBuf buf = this.buf;
|
||||
final int readerIdx = buf.readerIndex();
|
||||
if (buf.readableBytes() < utflen) {
|
||||
throw new EOFException();
|
||||
}
|
||||
|
||||
final String result;
|
||||
if (buf.hasArray()) {
|
||||
// Directly pass in the backing array
|
||||
result = decodeFromArray(buf.array(), buf.arrayOffset() + readerIdx, utflen);
|
||||
buf.readerIndex(readerIdx + utflen);
|
||||
} else {
|
||||
// We need to construct some array for the String anyway, so reading it into an array is fine;
|
||||
// share the byte array.
|
||||
final byte[] data = ensureBytes(utflen);
|
||||
buf.readBytes(data, 0, utflen);
|
||||
result = decodeFromArray(data, 0, utflen);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String decodeFromArray(final byte[] data, final int offset, final int utflen) throws UTFDataFormatException {
|
||||
// Go through ASCII symbols and directly pass through as a latin-1 string if possible
|
||||
int i = 0;
|
||||
while (i < utflen && data[offset + i] >= 0) {
|
||||
i++;
|
||||
}
|
||||
if (i == utflen) {
|
||||
return new String(data, offset, utflen, StandardCharsets.ISO_8859_1);
|
||||
}
|
||||
|
||||
// Continue with a regular UTF-8 char decode
|
||||
final char[] chars = ensureChars(utflen);
|
||||
for (int j = 0; j < i; j++) {
|
||||
chars[j] = (char) data[offset + j];
|
||||
}
|
||||
final int charCount = decode(data, offset + i, offset + utflen, chars, i);
|
||||
return new String(chars, 0, charCount);
|
||||
}
|
||||
|
||||
private static int decode(final byte[] data, int pos, final int end, final char[] chars, int charCount) throws UTFDataFormatException {
|
||||
// From DataInputStream
|
||||
while (pos < end) {
|
||||
final int c = data[pos] & 0xff;
|
||||
switch (c >> 4) {
|
||||
case 0, 1, 2, 3, 4, 5, 6, 7 -> {
|
||||
pos++;
|
||||
chars[charCount++] = (char) c;
|
||||
}
|
||||
case 12, 13 -> {
|
||||
if (pos + 2 > end) {
|
||||
throw new UTFDataFormatException("malformed input: partial character at end");
|
||||
}
|
||||
final int char2 = data[pos + 1];
|
||||
if ((char2 & 0xC0) != 0x80) {
|
||||
throw new UTFDataFormatException("malformed input around byte " + (pos + 2));
|
||||
}
|
||||
chars[charCount++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
pos += 2;
|
||||
}
|
||||
case 14 -> {
|
||||
if (pos + 3 > end) {
|
||||
throw new UTFDataFormatException("malformed input: partial character at end");
|
||||
}
|
||||
final int char2 = data[pos + 1];
|
||||
final int char3 = data[pos + 2];
|
||||
if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) {
|
||||
throw new UTFDataFormatException("malformed input around byte " + (pos + 2));
|
||||
}
|
||||
chars[charCount++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F));
|
||||
pos += 3;
|
||||
}
|
||||
default -> throw new UTFDataFormatException("malformed input around byte " + pos);
|
||||
}
|
||||
}
|
||||
return charCount;
|
||||
}
|
||||
|
||||
private byte[] ensureBytes(final int len) {
|
||||
if (bytearr.length < len) {
|
||||
bytearr = new byte[Math.max(len, 64)];
|
||||
}
|
||||
return bytearr;
|
||||
}
|
||||
|
||||
private char[] ensureChars(final int len) {
|
||||
if (chararr.length < len) {
|
||||
chararr = new char[Math.max(len, 64)];
|
||||
}
|
||||
return chararr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() {
|
||||
return buf.readableBytes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(final int readlimit) {
|
||||
buf.markReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean markSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (!buf.isReadable()) {
|
||||
return -1;
|
||||
}
|
||||
return buf.readByte() & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] b, final int off, int len) throws IOException {
|
||||
final int available = buf.readableBytes();
|
||||
if (available == 0) {
|
||||
return -1;
|
||||
}
|
||||
len = Math.min(available, len);
|
||||
buf.readBytes(b, off, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
buf.resetReaderIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(final long n) throws IOException {
|
||||
if (n > Integer.MAX_VALUE) {
|
||||
return skipBytes(Integer.MAX_VALUE);
|
||||
} else {
|
||||
return skipBytes((int) n);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readBoolean() throws IOException {
|
||||
checkAvailable(1);
|
||||
return buf.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte readByte() throws IOException {
|
||||
checkAvailable(1);
|
||||
return buf.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char readChar() {
|
||||
return (char) buf.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble() {
|
||||
return Double.longBitsToDouble(buf.readLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat() throws IOException {
|
||||
return Float.intBitsToFloat(buf.readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(final byte[] b) throws IOException {
|
||||
readFully(b, 0, b.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFully(final byte[] b, final int off, final int len) throws IOException {
|
||||
if (len < 0) {
|
||||
throw new IndexOutOfBoundsException("fieldSize cannot be a negative number");
|
||||
}
|
||||
checkAvailable(len);
|
||||
buf.readBytes(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt() throws IOException {
|
||||
checkAvailable(4);
|
||||
return buf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readLine() {
|
||||
// Don't reuse the StringBuilder here, this is not relevant for packet reading
|
||||
final StringBuilder lineBuf = new StringBuilder();
|
||||
int available = available();
|
||||
if (available == 0) {
|
||||
return null;
|
||||
}
|
||||
loop:
|
||||
do {
|
||||
int c = buf.readUnsignedByte();
|
||||
--available;
|
||||
switch (c) {
|
||||
case '\n':
|
||||
break loop;
|
||||
|
||||
case '\r':
|
||||
if (available > 0 && (char) buf.getUnsignedByte(buf.readerIndex()) == '\n') {
|
||||
buf.skipBytes(1);
|
||||
--available;
|
||||
}
|
||||
break loop;
|
||||
|
||||
default:
|
||||
lineBuf.append((char) c);
|
||||
}
|
||||
} while (available > 0);
|
||||
return !lineBuf.isEmpty() ? lineBuf.toString() : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public long readLong() throws IOException {
|
||||
checkAvailable(8);
|
||||
return buf.readLong();
|
||||
}
|
||||
|
||||
@Override
|
||||
public short readShort() throws IOException {
|
||||
checkAvailable(2);
|
||||
return buf.readShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedByte() {
|
||||
return buf.readByte() & 0xff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readUnsignedShort() {
|
||||
return buf.readShort() & 0xffff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skipBytes(final int n) {
|
||||
final int nBytes = Math.min(available(), n);
|
||||
buf.skipBytes(nBytes);
|
||||
return nBytes;
|
||||
}
|
||||
|
||||
private void checkAvailable(final int fieldSize) throws IOException {
|
||||
if (fieldSize > buf.readableBytes()) {
|
||||
throw new EOFException("fieldSize is too long! Length is " + fieldSize + ", but maximum is " + available());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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.io;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufOutputStream;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UTFDataFormatException;
|
||||
|
||||
/**
|
||||
* {@link ByteBufOutputStream} alternative with a more fine-tuned {@link #writeUTF(String)} implementation
|
||||
* for fast writing of NBT strings.
|
||||
*/
|
||||
public final class FastByteBufOutputStream extends OutputStream implements DataOutput {
|
||||
|
||||
private final ByteBuf buf;
|
||||
|
||||
public FastByteBufOutputStream(final ByteBuf buffer) {
|
||||
Preconditions.checkNotNull(buffer);
|
||||
this.buf = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeUTF(final String s) throws IOException {
|
||||
// This writes the individual characters to the buffer without an intermediary array.
|
||||
// What's lost from no longer bulk writing is gained from avoiding allocation and multiple
|
||||
// extra iterations of the full string.
|
||||
final int len = s.length();
|
||||
if (len == 0) {
|
||||
buf.writeShort(0);
|
||||
return;
|
||||
}
|
||||
if (len > 65535) {
|
||||
throw new UTFDataFormatException("encoded string too long: " + len + " characters");
|
||||
}
|
||||
|
||||
// Reserve space for the length prefix
|
||||
final int lenIndex = buf.writerIndex();
|
||||
final int startIndex = lenIndex + Short.BYTES;
|
||||
buf.ensureWritable(Short.BYTES + len); // even if it ends up being larger, netty does a good job at avoiding constant resizing
|
||||
buf.writeShort(len);
|
||||
|
||||
// Start writing single ASCII bytes
|
||||
int i = 0;
|
||||
for (; i < len; i++) {
|
||||
final char c = s.charAt(i);
|
||||
if (c >= 0x80 || c == 0) break;
|
||||
buf.writeByte(c);
|
||||
}
|
||||
|
||||
if (i == len) {
|
||||
return; // done
|
||||
}
|
||||
|
||||
// Write the rest
|
||||
for (; i < len; i++) {
|
||||
final char c = s.charAt(i);
|
||||
if (c < 0x80 && c != 0) {
|
||||
buf.writeByte(c);
|
||||
} else if (c >= 0x800) {
|
||||
buf.writeByte(0xE0 | ((c >> 12) & 0x0F));
|
||||
buf.writeByte(0x80 | ((c >> 6) & 0x3F));
|
||||
buf.writeByte(0x80 | (c & 0x3F));
|
||||
} else {
|
||||
buf.writeByte(0xC0 | ((c >> 6) & 0x1F));
|
||||
buf.writeByte(0x80 | (c & 0x3F));
|
||||
}
|
||||
}
|
||||
|
||||
// Don't do another round of counting just for the bounds check; check at the end,
|
||||
// even if that means that in the worst case this might have already written a good bit over the threshold.
|
||||
final int utflen = buf.writerIndex() - startIndex;
|
||||
if (utflen > 65535) {
|
||||
buf.writerIndex(lenIndex);
|
||||
throw new UTFDataFormatException("encoded string too long: " + utflen + " bytes");
|
||||
}
|
||||
|
||||
// Set the actual length
|
||||
buf.setShort(lenIndex, utflen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final byte[] b, final int off, final int len) throws IOException {
|
||||
buf.writeBytes(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final byte[] b) throws IOException {
|
||||
buf.writeBytes(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final int b) throws IOException {
|
||||
buf.writeByte(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBoolean(final boolean v) throws IOException {
|
||||
buf.writeBoolean(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeByte(final int v) throws IOException {
|
||||
buf.writeByte(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(final String s) throws IOException {
|
||||
final int length = s.length();
|
||||
buf.ensureWritable(length);
|
||||
final int offset = buf.writerIndex();
|
||||
for (int i = 0; i < length; i++) {
|
||||
buf.setByte(offset + i, (byte) s.charAt(i));
|
||||
}
|
||||
buf.writerIndex(offset + length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChar(final int v) {
|
||||
buf.writeChar(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeChars(final String s) {
|
||||
final int len = s.length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
buf.writeChar(s.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDouble(final double v) throws IOException {
|
||||
buf.writeDouble(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeFloat(final float v) throws IOException {
|
||||
buf.writeFloat(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeInt(final int v) throws IOException {
|
||||
buf.writeInt(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeLong(final long v) throws IOException {
|
||||
buf.writeLong(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeShort(final int v) throws IOException {
|
||||
buf.writeShort((short) v);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
package com.viaversion.viaversion.util;
|
||||
|
||||
import java.util.function.IntToLongFunction;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
public final class CompactArrayUtil {
|
||||
private static final long[] RECIPROCAL_MULT_AND_ADD = {
|
||||
@@ -51,40 +52,39 @@ public final class CompactArrayUtil {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public static long[] createCompactArrayWithPadding(int bitsPerEntry, int entries, IntToLongFunction valueGetter) {
|
||||
long maxEntryValue = (1L << bitsPerEntry) - 1;
|
||||
char valuesPerLong = (char) (64 / bitsPerEntry);
|
||||
int magicIndex = valuesPerLong - 1;
|
||||
long divideAdd = RECIPROCAL_MULT_AND_ADD[magicIndex];
|
||||
long divideMul = divideAdd != 0 ? divideAdd : 0x80000000L; // Special case for the 0x80000000/0x00000000 tuple
|
||||
int divideShift = RECIPROCAL_RIGHT_SHIFT[magicIndex];
|
||||
int size = (entries + valuesPerLong - 1) / valuesPerLong;
|
||||
public static long[] createCompactArrayWithPadding(int bitsPerEntry, int entries, IntUnaryOperator valueGetter) {
|
||||
final long maxEntryValue = (1L << bitsPerEntry) - 1;
|
||||
final int valuesPerLong = (char) (64 / bitsPerEntry);
|
||||
final int size = (entries + valuesPerLong - 1) / valuesPerLong;
|
||||
final long[] data = new long[size];
|
||||
|
||||
long[] data = new long[size];
|
||||
|
||||
for (int i = 0; i < entries; i++) {
|
||||
long value = valueGetter.applyAsLong(i);
|
||||
int cellIndex = (int) (i * divideMul + divideAdd >> 32L >> divideShift);
|
||||
int bitIndex = (i - cellIndex * valuesPerLong) * bitsPerEntry;
|
||||
data[cellIndex] = data[cellIndex] & ~(maxEntryValue << bitIndex) | (value & maxEntryValue) << bitIndex;
|
||||
int i = 0;
|
||||
for (int cellIndex = 0; cellIndex < size; cellIndex++) {
|
||||
long cell = 0L;
|
||||
int bitIndex = 0;
|
||||
final int limit = Math.min(i + valuesPerLong, entries);
|
||||
while (i < limit) {
|
||||
cell |= (valueGetter.applyAsInt(i++) & maxEntryValue) << bitIndex;
|
||||
bitIndex += bitsPerEntry;
|
||||
}
|
||||
data[cellIndex] = cell;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public static void iterateCompactArrayWithPadding(int bitsPerEntry, int entries, long[] data, BiIntConsumer consumer) {
|
||||
long maxEntryValue = (1L << bitsPerEntry) - 1;
|
||||
char valuesPerLong = (char) (64 / bitsPerEntry);
|
||||
int magicIndex = valuesPerLong - 1;
|
||||
long divideAdd = RECIPROCAL_MULT_AND_ADD[magicIndex];
|
||||
long divideMul = divideAdd != 0 ? divideAdd : 0x80000000L;
|
||||
int divideShift = RECIPROCAL_RIGHT_SHIFT[magicIndex];
|
||||
final long maxEntryValue = (1L << bitsPerEntry) - 1;
|
||||
final int valuesPerLong = 64 / bitsPerEntry;
|
||||
final int size = data.length;
|
||||
|
||||
for (int i = 0; i < entries; i++) {
|
||||
int cellIndex = (int) (i * divideMul + divideAdd >> 32L >> divideShift);
|
||||
int bitIndex = (i - cellIndex * valuesPerLong) * bitsPerEntry;
|
||||
int value = (int) (data[cellIndex] >> bitIndex & maxEntryValue);
|
||||
consumer.consume(i, value);
|
||||
int i = 0;
|
||||
for (int cellIndex = 0; cellIndex < size; cellIndex++) {
|
||||
long cell = data[cellIndex];
|
||||
final int limit = Math.min(i + valuesPerLong, entries);
|
||||
while (i < limit) {
|
||||
consumer.consume(i++, (int) (cell & maxEntryValue));
|
||||
cell >>>= bitsPerEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class Key {
|
||||
* Creates a new key with the given namespace and path.
|
||||
*
|
||||
* @param namespace the namespace of the identifier
|
||||
* @param path the path of the identifier
|
||||
* @param path the path of the identifier
|
||||
* @return a new key with the given namespace and path
|
||||
*/
|
||||
public static Key of(final String namespace, final String path) {
|
||||
|
||||
@@ -49,7 +49,7 @@ fun ShadowJar.configureRelocations() {
|
||||
}
|
||||
|
||||
fun ShadowJar.configureExcludes() {
|
||||
// FastUtil - we only want object, int, and certain reference maps
|
||||
// FastUtil - we only want object, int, long-to-object, and certain reference maps
|
||||
// Object types
|
||||
exclude("it/unimi/dsi/fastutil/*/*2Reference*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Reference2Int*")
|
||||
@@ -58,17 +58,23 @@ fun ShadowJar.configureExcludes() {
|
||||
exclude("it/unimi/dsi/fastutil/*/*Short*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Float*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Double*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Long*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*2Long*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Char*")
|
||||
// Map types
|
||||
exclude("it/unimi/dsi/fastutil/*/*Custom*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Tree*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Heap*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Queue*")
|
||||
exclude("it/unimi/dsi/fastutil/longs/*2Int*")
|
||||
exclude("it/unimi/dsi/fastutil/longs/*ArrayMap*")
|
||||
exclude("it/unimi/dsi/fastutil/longs/*LinkedOpenHashMap*")
|
||||
exclude("it/unimi/dsi/fastutil/longs/*SortedMap*")
|
||||
// Crossing fingers
|
||||
exclude("it/unimi/dsi/fastutil/*Big*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Big*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Synchronized*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Unmodifiable*")
|
||||
// More
|
||||
exclude("it/unimi/dsi/fastutil/io/TextIO")
|
||||
exclude("it/unimi/dsi/fastutil/io/TextIO.class")
|
||||
exclude("it/unimi/dsi/fastutil/io/BinIO.class")
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
plugins {
|
||||
base
|
||||
eclipse
|
||||
id("via.build-logic")
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,20 @@ public final class NMSUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?> nms(String className, String... fallbackFullClassNames) throws ClassNotFoundException {
|
||||
try {
|
||||
return Class.forName(NMS + "." + className);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
for (final String fallbackFullClassName : fallbackFullClassNames) {
|
||||
try {
|
||||
return Class.forName(fallbackFullClassName);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
throw new ClassNotFoundException(className);
|
||||
}
|
||||
|
||||
public static Class<?> obc(String className) throws ClassNotFoundException {
|
||||
return Class.forName(BASE + "." + className);
|
||||
}
|
||||
|
||||
+6
-3
@@ -105,7 +105,8 @@ public class BukkitViaInjector extends LegacyViaInjector {
|
||||
// Grab the ping class and find the field to access it
|
||||
Class<?> pingClazz = NMSUtil.nms(
|
||||
"ServerPing",
|
||||
"net.minecraft.network.protocol.status.ServerPing"
|
||||
"net.minecraft.network.protocol.status.ServerPing",
|
||||
"net.minecraft.network.protocol.status.ServerStatus"
|
||||
);
|
||||
Object ping = null;
|
||||
for (Field field : serverClazz.getDeclaredFields()) {
|
||||
@@ -120,7 +121,8 @@ public class BukkitViaInjector extends LegacyViaInjector {
|
||||
// Now get the ServerData inside ServerPing
|
||||
Class<?> serverDataClass = NMSUtil.nms(
|
||||
"ServerPing$ServerData",
|
||||
"net.minecraft.network.protocol.status.ServerPing$ServerData"
|
||||
"net.minecraft.network.protocol.status.ServerPing$ServerData",
|
||||
"net.minecraft.network.protocol.status.ServerStatus$Version"
|
||||
);
|
||||
Object serverData = null;
|
||||
for (Field field : pingClazz.getDeclaredFields()) {
|
||||
@@ -155,7 +157,8 @@ public class BukkitViaInjector extends LegacyViaInjector {
|
||||
);
|
||||
Class<?> connectionClass = NMSUtil.nms(
|
||||
"ServerConnection",
|
||||
"net.minecraft.server.network.ServerConnection"
|
||||
"net.minecraft.server.network.ServerConnection",
|
||||
"net.minecraft.server.network.ServerConnectionListener"
|
||||
);
|
||||
|
||||
Object server = ReflectionUtil.invokeStatic(serverClass, "getServer");
|
||||
|
||||
@@ -267,8 +267,8 @@ public class ViaManagerImpl implements ViaManager {
|
||||
platform.getLogger().warning("ViaVersion no longer officially supports this version of Java, only offering unsupported compatibility builds.");
|
||||
platform.getLogger().warning("See https://github.com/ViaVersion/ViaVersion/releases/tag/5.0.0 for more information.");
|
||||
} else if (version < 21) {
|
||||
platform.getLogger().warning("Please update your Java runtime to at least Java 21 (your version is " + javaVersion + ").");
|
||||
platform.getLogger().warning("At some point in the future, ViaVersion will no longer be compatible with this version of Java.");
|
||||
// platform.getLogger().warning("Please update your Java runtime to at least Java 21 (your version is " + javaVersion + ").");
|
||||
// platform.getLogger().warning("At some point in the future, ViaVersion will no longer be compatible with this version of Java.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+102
-78
@@ -2,23 +2,18 @@
|
||||
* 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:
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* 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.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.protocol;
|
||||
|
||||
@@ -27,6 +22,7 @@ import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.entity.EntityTracker;
|
||||
import com.viaversion.viaversion.api.data.item.ItemHasher;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
@@ -39,10 +35,17 @@ import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypeMap;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.rewriter.MappingDataListener;
|
||||
import com.viaversion.viaversion.api.rewriter.Rewriter;
|
||||
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
import com.viaversion.viaversion.data.item.ItemHasherBase;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.exception.InformativeException;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.TagRewriter;
|
||||
import com.viaversion.viaversion.rewriter.text.ComponentRewriterBase;
|
||||
import com.viaversion.viaversion.util.ProtocolLogger;
|
||||
import com.viaversion.viaversion.util.ProtocolUtil;
|
||||
import java.util.HashMap;
|
||||
@@ -74,6 +77,8 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
private final Map<Class<?>, Object> storedObjects = new HashMap<>();
|
||||
private boolean initialized;
|
||||
private ProtocolLogger logger;
|
||||
private ProtocolVersion serverVersion;
|
||||
private ProtocolVersion clientVersion;
|
||||
|
||||
@Deprecated
|
||||
protected AbstractProtocol() {
|
||||
@@ -104,8 +109,12 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
if (logger == null) {
|
||||
logger = createLogger();
|
||||
}
|
||||
|
||||
// Apply shared registrations based on protocol version range
|
||||
// Run before registerPackets, so implementations have to call append intentionally
|
||||
applySharedRegistrations();
|
||||
|
||||
registerPackets();
|
||||
registerConfigurationChangeHandlers();
|
||||
|
||||
// Register the rest of the ids with no handlers if necessary
|
||||
if (unmappedClientboundPacketType != null && mappedClientboundPacketType != null
|
||||
@@ -128,33 +137,15 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
}
|
||||
}
|
||||
|
||||
protected ProtocolLogger createLogger() {
|
||||
return new ProtocolLogger(getClass());
|
||||
/**
|
||||
* Applies shared registrations. Can be overridden to remove or add registrations.
|
||||
*/
|
||||
protected void applySharedRegistrations() {
|
||||
SharedRegistrations.defaultRegistrations().applyMatching(this);
|
||||
}
|
||||
|
||||
protected void registerConfigurationChangeHandlers() {
|
||||
// Register handlers for protocol state switching
|
||||
// Assuming ids will change too often, it is cleaner to register them here instead of the base protocols,
|
||||
// even if there will be multiple of these handlers
|
||||
final SU configurationAcknowledgedPacket = configurationAcknowledgedPacket();
|
||||
if (configurationAcknowledgedPacket != null) {
|
||||
appendServerbound(configurationAcknowledgedPacket, setClientStateHandler(State.CONFIGURATION));
|
||||
}
|
||||
|
||||
final CU startConfigurationPacket = startConfigurationPacket();
|
||||
if (startConfigurationPacket != null) {
|
||||
appendClientbound(startConfigurationPacket, startConfigurationHandler());
|
||||
}
|
||||
|
||||
final SU finishConfigurationPacket = serverboundFinishConfigurationPacket();
|
||||
if (finishConfigurationPacket != null) {
|
||||
appendServerbound(finishConfigurationPacket, setClientStateHandler(State.PLAY));
|
||||
}
|
||||
|
||||
final CU clientboundFinishConfigurationPacket = clientboundFinishConfigurationPacket();
|
||||
if (clientboundFinishConfigurationPacket != null) {
|
||||
appendClientbound(clientboundFinishConfigurationPacket, setServerStateHandler(State.PLAY));
|
||||
}
|
||||
protected ProtocolLogger createLogger() {
|
||||
return new ProtocolLogger(getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,6 +168,20 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceClientbound(final CU type, @Nullable final PacketHandler handler) {
|
||||
final PacketMapping mapping = clientboundMappings.mappedPacket(type.state(), type.getId());
|
||||
Preconditions.checkNotNull(mapping, "Packet %s has no handler to replace", type);
|
||||
mapping.setHandler(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceServerbound(final SU type, @Nullable final PacketHandler handler) {
|
||||
final PacketMapping mapping = serverboundMappings.mappedPacket(type.state(), type.getId());
|
||||
Preconditions.checkNotNull(mapping, "Packet %s has no handler to replace", type);
|
||||
mapping.setHandler(handler);
|
||||
}
|
||||
|
||||
private <U extends PacketType, M extends PacketType> void registerPacketIdChanges(
|
||||
Map<State, PacketTypeMap<U>> unmappedPacketTypes,
|
||||
Map<State, PacketTypeMap<M>> mappedPacketTypes,
|
||||
@@ -203,17 +208,10 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
}
|
||||
}
|
||||
|
||||
public void registerFinishConfiguration(final CU packetType, final PacketHandler handler) {
|
||||
registerClientbound(packetType, wrapper -> {
|
||||
// TODO Temporary solution to handle the finish configuration packet already having changed our tracked protocol state in a previous handler
|
||||
wrapper.user().getProtocolInfo().setServerState(State.CONFIGURATION);
|
||||
handler.handle(wrapper);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void loadMappingData() {
|
||||
getMappingData().load();
|
||||
initialize();
|
||||
onMappingDataLoaded();
|
||||
}
|
||||
|
||||
@@ -248,10 +246,21 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
}
|
||||
}
|
||||
|
||||
protected void addEntityTracker(UserConnection connection) {
|
||||
final EntityType playerEntityType = getEntityRewriter().typeFromId("player");
|
||||
Preconditions.checkNotNull(playerEntityType, "Player entity type not found");
|
||||
connection.addEntityTracker(this.getClass(), new EntityTrackerBase(connection, playerEntityType));
|
||||
}
|
||||
|
||||
protected void addEntityTracker(UserConnection connection, EntityTracker tracker) {
|
||||
connection.addEntityTracker(this.getClass(), tracker);
|
||||
}
|
||||
|
||||
protected void addItemHasher(UserConnection connection) {
|
||||
connection.addItemHasher(this.getClass(), new ItemHasherBase(this, connection));
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
protected void addItemHasher(UserConnection connection, ItemHasher hasher) {
|
||||
connection.addItemHasher(this.getClass(), hasher);
|
||||
}
|
||||
@@ -273,20 +282,44 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
return PacketMappings.arrayMappings();
|
||||
}
|
||||
|
||||
protected @Nullable SU configurationAcknowledgedPacket() {
|
||||
return packetTypesProvider.unmappedServerboundType(State.PLAY, "CONFIGURATION_ACKNOWLEDGED");
|
||||
/**
|
||||
* Returns the server protocol version for this protocol,
|
||||
* or null if not set (e.g. for base protocols).
|
||||
*
|
||||
* @return the server protocol version
|
||||
*/
|
||||
public @Nullable ProtocolVersion getServerVersion() {
|
||||
return serverVersion;
|
||||
}
|
||||
|
||||
protected @Nullable CU startConfigurationPacket() {
|
||||
return packetTypesProvider.unmappedClientboundType(State.PLAY, "START_CONFIGURATION");
|
||||
/**
|
||||
* Sets the server protocol version for this protocol.
|
||||
* Called by the protocol manager before {@link #initialize()}.
|
||||
*
|
||||
* @param serverVersion the server protocol version
|
||||
*/
|
||||
public void setServerVersion(final ProtocolVersion serverVersion) {
|
||||
this.serverVersion = serverVersion;
|
||||
}
|
||||
|
||||
protected @Nullable SU serverboundFinishConfigurationPacket() {
|
||||
return packetTypesProvider.unmappedServerboundType(State.CONFIGURATION, "FINISH_CONFIGURATION");
|
||||
/**
|
||||
* Returns the client protocol version for this protocol,
|
||||
* or null if not set (e.g. for base protocols).
|
||||
*
|
||||
* @return the client protocol version for this protocol
|
||||
*/
|
||||
public @Nullable ProtocolVersion getClientVersion() {
|
||||
return clientVersion;
|
||||
}
|
||||
|
||||
protected @Nullable CU clientboundFinishConfigurationPacket() {
|
||||
return packetTypesProvider.unmappedClientboundType(State.CONFIGURATION, "FINISH_CONFIGURATION");
|
||||
/**
|
||||
* Sets the client protocol version for this protocol.
|
||||
* Called by the protocol manager before {@link #initialize()}.
|
||||
*
|
||||
* @param clientVersion the client protocol version for this protocol
|
||||
*/
|
||||
public void setClientVersion(final ProtocolVersion clientVersion) {
|
||||
this.clientVersion = clientVersion;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------
|
||||
@@ -297,7 +330,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
PacketMapping packetMapping = PacketMapping.of(mappedPacketId, handler);
|
||||
if (!override && serverboundMappings.hasMapping(state, unmappedPacketId)) {
|
||||
Via.getPlatform().getLogger().log(Level.WARNING, unmappedPacketId + " already registered!" +
|
||||
" If this override is intentional, set override to true. Stacktrace: ", new Exception());
|
||||
" If this override is intentional, use replaceServerbound instead. Stacktrace: ", new Exception());
|
||||
}
|
||||
serverboundMappings.addMapping(state, unmappedPacketId, packetMapping);
|
||||
}
|
||||
@@ -313,7 +346,7 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
PacketMapping packetMapping = PacketMapping.of(mappedPacketId, handler);
|
||||
if (!override && clientboundMappings.hasMapping(state, unmappedPacketId)) {
|
||||
Via.getPlatform().getLogger().log(Level.WARNING, unmappedPacketId + " already registered!" +
|
||||
" If override is intentional, set override to true. Stacktrace: ", new Exception());
|
||||
" If override is intentional, use replaceClientbound instead. Stacktrace: ", new Exception());
|
||||
}
|
||||
clientboundMappings.addMapping(state, unmappedPacketId, packetMapping);
|
||||
}
|
||||
@@ -373,8 +406,8 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
|
||||
PacketMapping packetMapping = PacketMapping.of(mappedPacketType, handler);
|
||||
if (!override && packetMappings.hasMapping(packetType)) {
|
||||
getLogger().log(Level.WARNING, packetType + " already registered!" +
|
||||
" If override is intentional, set override to true. Stacktrace: ", new Exception());
|
||||
throw new IllegalArgumentException("Packet type " + packetType + " already registered! If override is intentional, use "
|
||||
+ (packetType.direction() == Direction.SERVERBOUND ? "replaceServerbound" : "replaceClientbound") + " instead.");
|
||||
}
|
||||
packetMappings.addMapping(packetType, packetMapping);
|
||||
}
|
||||
@@ -443,6 +476,14 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
return logger;
|
||||
}
|
||||
|
||||
public com.viaversion.viaversion.rewriter.@Nullable BlockRewriter<CU> getBlockRewriter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public @Nullable RecipeDisplayRewriter<CU> getRecipeRewriter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void printRemapError(Direction direction, State state, int unmappedPacketId, int mappedPacketId, InformativeException e) {
|
||||
// Don't print errors during handshake/login/status
|
||||
if (state != State.PLAY && direction == Direction.SERVERBOUND && !Via.getManager().debugHandler().enabled()) {
|
||||
@@ -472,23 +513,6 @@ public abstract class AbstractProtocol<CU extends ClientboundPacketType, CM exte
|
||||
}
|
||||
}
|
||||
|
||||
private PacketHandler setClientStateHandler(final State state) {
|
||||
return wrapper -> wrapper.user().getProtocolInfo().setClientState(state);
|
||||
}
|
||||
|
||||
private PacketHandler setServerStateHandler(final State state) {
|
||||
return wrapper -> wrapper.user().getProtocolInfo().setServerState(state);
|
||||
}
|
||||
|
||||
private PacketHandler startConfigurationHandler() {
|
||||
return setServerStateHandler(State.CONFIGURATION).then(wrapper -> {
|
||||
// Mimic client behaviour
|
||||
final EntityTracker tracker = wrapper.user().getEntityTracker(getClass());
|
||||
if (tracker != null) {
|
||||
tracker.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PacketTypesProvider<CU, CM, SM, SU> getPacketTypesProvider() {
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.codec;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.codec.CodecContext;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
@@ -48,4 +49,9 @@ public record CodecRegistryContext(Protocol<?, ?, ?, ?> protocol, RegistryAccess
|
||||
final VersionedTypesHolder types = mapped ? protocol.mappedTypes() : protocol.types();
|
||||
return (NOT_IMPLEMENTED.isEmpty() || !NOT_IMPLEMENTED.contains(key)) && types.structuredDataKeys().supportsOps(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserConnection connection() {
|
||||
return registryAccess.connection();
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.handler.codec.CodecException;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -52,7 +53,6 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Function;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class UserConnectionImpl implements UserConnection {
|
||||
|
||||
@@ -27,14 +27,17 @@ import com.viaversion.viaversion.api.data.entity.StoredEntityData;
|
||||
import com.viaversion.viaversion.api.data.entity.TrackedEntity;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import com.viaversion.viaversion.util.KeyMappings;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeListener {
|
||||
protected final Int2ObjectMap<TrackedEntity> entities = new Int2ObjectOpenHashMap<>();
|
||||
private final Map<String, KeyMappings> registryKeyMappings = new HashMap<>();
|
||||
private final UserConnection connection;
|
||||
private final EntityType playerType;
|
||||
private Integer clientEntityId;
|
||||
@@ -115,6 +118,7 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
}
|
||||
|
||||
clientEntityId = null;
|
||||
registryKeyMappings.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,4 +226,14 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
public void setDimensions(Map<String, DimensionData> dimensions) {
|
||||
this.dimensions = dimensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable KeyMappings registryKeys(String registryKey) {
|
||||
return registryKeyMappings.get(Key.stripMinecraftNamespace(registryKey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRegistryKeys(String registryKey, KeyMappings mappings) {
|
||||
registryKeyMappings.put(Key.stripMinecraftNamespace(registryKey), mappings);
|
||||
}
|
||||
}
|
||||
@@ -34,22 +34,20 @@ import com.viaversion.viaversion.codec.CodecRegistryContext;
|
||||
import com.viaversion.viaversion.codec.hash.HashFunction;
|
||||
import com.viaversion.viaversion.codec.hash.HashOps;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class ItemHasherBase implements ItemHasher {
|
||||
|
||||
public static int UNKNOWN_HASH = 399825415; // some random-ish number, from hashing Integer.MIN_VALUE+1 with crc32c
|
||||
private final Map<Integer, HashedItem> hashes = CacheBuilder.newBuilder().concurrencyLevel(1).maximumSize(1024).<Integer, HashedItem>build().asMap();
|
||||
private final Map<Integer, OriginalHashedItem> hashes = CacheBuilder.newBuilder().concurrencyLevel(1).maximumSize(1024).<Integer, OriginalHashedItem>build().asMap();
|
||||
protected final UserConnection connection;
|
||||
private boolean processingClientboundInventoryPacket;
|
||||
private final CodecContext context;
|
||||
private final CodecContext mappedContext;
|
||||
|
||||
public ItemHasherBase(final Protocol<?, ?, ?, ?> protocol, final UserConnection connection) {
|
||||
final RegistryAccess registryAccess = RegistryAccess.of(protocol);
|
||||
final RegistryAccess registryAccess = RegistryAccess.of(protocol, connection);
|
||||
this.context = new CodecRegistryContext(protocol, registryAccess, false);
|
||||
this.mappedContext = new CodecRegistryContext(protocol, registryAccess, true);
|
||||
this.connection = connection;
|
||||
@@ -58,7 +56,7 @@ public class ItemHasherBase implements ItemHasher {
|
||||
/**
|
||||
* Returns the hashed item for the given item. Not all data may be successfully hashed.
|
||||
*
|
||||
* @param item the item to hash
|
||||
* @param item the item to hash
|
||||
* @param mapped whether the item is mapped to the client version
|
||||
* @return the hashed item
|
||||
*/
|
||||
@@ -83,25 +81,26 @@ public class ItemHasherBase implements ItemHasher {
|
||||
/**
|
||||
* Tracks the data for the given data container, storing the original hashes via the now transformed data hashes.
|
||||
*
|
||||
* @param customData custom_data tag
|
||||
* @param customData custom_data tag
|
||||
* @param originalHashedItem the original (pre-transformed) hashed item
|
||||
* @param backupTagName protocol-specific backup tag name where the item should become a regular hashed item again
|
||||
*/
|
||||
public void trackOriginalHashedItem(final CompoundTag customData, final HashedItem originalHashedItem) {
|
||||
public void trackOriginalHashedItem(final CompoundTag customData, final HashedItem originalHashedItem, final String backupTagName) {
|
||||
// Store them via the custom_data hash, which includes the original data hashes.
|
||||
// Not perfect (as opposed to storing it by the full hashed item), but good enough. In the rare occasion there is a collision, we ignore it without issues.
|
||||
final int customDataHash = hashTag(customData);
|
||||
this.hashes.put(customDataHash, originalHashedItem);
|
||||
this.hashes.put(customDataHash, new OriginalHashedItem(originalHashedItem, backupTagName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of the original hashed item for a given custom_data hash.
|
||||
*
|
||||
* @param customDataHash custom_data hash
|
||||
* @param clientItem the hashed item from the client that the original should be retrieved for
|
||||
* @param clientItem the hashed item from the client that the original should be retrieved for
|
||||
* @return the original hashed item, or null if not found
|
||||
*/
|
||||
public @Nullable HashedItem originalHashedItem(final int customDataHash, final HashedItem clientItem) {
|
||||
HashedItem originalItem = this.hashes.get(customDataHash);
|
||||
public @Nullable OriginalHashedItem originalHashedItem(final int customDataHash, final HashedItem clientItem) {
|
||||
OriginalHashedItem originalItem = this.hashes.get(customDataHash);
|
||||
if (originalItem == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.data.item;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.item.HashedItem;
|
||||
import com.viaversion.viaversion.api.minecraft.item.HashedStructuredItem;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
|
||||
/**
|
||||
* Marker class to avoid continuous hashing and restoration of items in every protocol.
|
||||
* Instead, this restores it once and passes the result through to the protocol that originally stored the backup.
|
||||
*/
|
||||
public final class OriginalHashedItem extends HashedStructuredItem {
|
||||
private final String backupTagName;
|
||||
|
||||
public OriginalHashedItem(final HashedItem item, final String backupTagName) {
|
||||
this(item.identifier(), item.amount(), item.dataHashesById(), item.removedDataIds(), backupTagName); // don't copy
|
||||
}
|
||||
|
||||
public OriginalHashedItem(final int identifier, final int amount, final String backupTagName) {
|
||||
super(identifier, amount);
|
||||
this.backupTagName = backupTagName;
|
||||
}
|
||||
|
||||
private OriginalHashedItem(final int identifier, final int amount, final Int2IntMap dataHashes, final IntSet removedData, final String backupTagName) {
|
||||
super(identifier, amount, dataHashes, removedData);
|
||||
this.backupTagName = backupTagName;
|
||||
}
|
||||
|
||||
public String backupTagName() {
|
||||
return backupTagName;
|
||||
}
|
||||
|
||||
public HashedItem asRegularItem() {
|
||||
return new HashedStructuredItem(identifier(), amount(), dataHashesById(), removedDataIds());
|
||||
}
|
||||
|
||||
@Override
|
||||
public OriginalHashedItem copy() {
|
||||
return new OriginalHashedItem(identifier(), amount(), new Int2IntOpenHashMap(dataHashesById()), new IntOpenHashSet(removedDataIds()), backupTagName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.SimpleProtocol;
|
||||
|
||||
/**
|
||||
* A simple protocol which does not have any packet types.
|
||||
* <p>
|
||||
* {@link AbstractProtocol} should be preferred over this class in most cases.
|
||||
*/
|
||||
public abstract class AbstractSimpleProtocol extends AbstractProtocol<SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes,
|
||||
SimpleProtocol.DummyPacketTypes, SimpleProtocol.DummyPacketTypes> implements SimpleProtocol {
|
||||
|
||||
protected AbstractSimpleProtocol() {
|
||||
super(null, null, null, null);
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.google.common.collect.Range;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingDataLoader;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolManager;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
@@ -38,6 +39,7 @@ import com.viaversion.viaversion.api.protocol.version.ServerProtocolVersion;
|
||||
import com.viaversion.viaversion.api.protocol.version.VersionType;
|
||||
import com.viaversion.viaversion.protocol.packet.PacketWrapperImpl;
|
||||
import com.viaversion.viaversion.protocol.packet.VersionedPacketTransformerImpl;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.def.DefaultRegistrations;
|
||||
import com.viaversion.viaversion.protocols.base.InitialBaseProtocol;
|
||||
import com.viaversion.viaversion.protocols.base.v1_16.ClientboundBaseProtocol1_16;
|
||||
import com.viaversion.viaversion.protocols.base.v1_7.ClientboundBaseProtocol1_7;
|
||||
@@ -95,6 +97,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -113,9 +116,7 @@ import java.util.concurrent.ForkJoinWorkerThread;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Function;
|
||||
import java.util.logging.Level;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class ProtocolManagerImpl implements ProtocolManager {
|
||||
@@ -146,6 +147,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
worker.setName("Via-Mappingloader-" + threadIndex.incrementAndGet());
|
||||
return worker;
|
||||
}, ForkJoinWorkerThread.getDefaultUncaughtExceptionHandler(), true);
|
||||
|
||||
DefaultRegistrations.apply();
|
||||
}
|
||||
|
||||
public void registerProtocols() {
|
||||
@@ -225,8 +228,11 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
|
||||
@Override
|
||||
public void registerProtocol(Protocol protocol, List<ProtocolVersion> supportedClientVersion, ProtocolVersion serverVersion) {
|
||||
// Register the protocol's handlers
|
||||
protocol.initialize();
|
||||
// Set the server version on AbstractProtocol instances before initialization
|
||||
if (protocol instanceof AbstractProtocol<?, ?, ?, ?> abstractProtocol) {
|
||||
abstractProtocol.setServerVersion(serverVersion);
|
||||
abstractProtocol.setClientVersion(supportedClientVersion.stream().max(ProtocolVersion::compareTo).orElseThrow());
|
||||
}
|
||||
|
||||
// Clear cache as this may make new routes.
|
||||
if (!pathCache.isEmpty()) {
|
||||
@@ -248,14 +254,22 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
refreshVersions();
|
||||
}
|
||||
|
||||
if (protocol.hasMappingDataToLoad()) {
|
||||
if (mappingLoaderExecutor != null) {
|
||||
// Submit mapping data loading
|
||||
addMappingLoaderFuture(protocol.getClass(), protocol::loadMappingData);
|
||||
// Load mapping data and register the protocol's handlers
|
||||
if (!protocol.hasMappingDataToLoad()) {
|
||||
protocol.initialize();
|
||||
return;
|
||||
}
|
||||
|
||||
// Submit mapping data loading
|
||||
if (mappingLoaderExecutor != null) {
|
||||
if (protocol.dependsOn() != null) {
|
||||
addMappingLoaderFuture(protocol.getClass(), protocol.dependsOn(), protocol::loadMappingData);
|
||||
} else {
|
||||
// Late protocol adding - just do it on the current thread
|
||||
protocol.loadMappingData();
|
||||
addMappingLoaderFuture(protocol.getClass(), protocol::loadMappingData);
|
||||
}
|
||||
} else {
|
||||
// Late protocol adding - just do it on the current thread
|
||||
protocol.loadMappingData();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,7 +498,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkForMappingCompletion() {
|
||||
public boolean checkForMappingCompletion(final boolean propagateErrors) {
|
||||
mappingLoaderLock.readLock().lock();
|
||||
try {
|
||||
if (mappingsLoaded) {
|
||||
@@ -496,6 +510,9 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
if (!future.isDone()) {
|
||||
return false;
|
||||
}
|
||||
if (propagateErrors) {
|
||||
future.join();
|
||||
}
|
||||
}
|
||||
|
||||
shutdownLoaderExecutor();
|
||||
@@ -507,7 +524,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
|
||||
@Override
|
||||
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Runnable runnable) {
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(runnable, mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(runnable, mappingLoaderExecutor)
|
||||
.whenComplete(($, t) -> logIfErrored(protocolClass, t));
|
||||
|
||||
mappingLoaderLock.writeLock().lock();
|
||||
try {
|
||||
@@ -519,8 +537,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
|
||||
@Override
|
||||
public void addMappingLoaderFuture(Class<? extends Protocol> protocolClass, Class<? extends Protocol> dependsOn, Runnable runnable) {
|
||||
CompletableFuture<Void> future = getMappingLoaderFuture(dependsOn)
|
||||
.whenCompleteAsync((v, throwable) -> runnable.run(), mappingLoaderExecutor).exceptionally(mappingLoaderThrowable(protocolClass));
|
||||
CompletableFuture<Void> future = getMappingLoaderFuture(dependsOn).thenRunAsync(runnable, mappingLoaderExecutor)
|
||||
.whenComplete(($, t) -> logIfErrored(protocolClass, t));
|
||||
|
||||
mappingLoaderLock.writeLock().lock();
|
||||
try {
|
||||
@@ -571,10 +589,9 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
MappingDataLoader.INSTANCE.clearCache();
|
||||
}
|
||||
|
||||
private Function<Throwable, Void> mappingLoaderThrowable(Class<? extends Protocol> protocolClass) {
|
||||
return throwable -> {
|
||||
Via.getPlatform().getLogger().log(Level.SEVERE, "Error during mapping loading of " + protocolClass.getSimpleName(), throwable);
|
||||
return null;
|
||||
};
|
||||
private void logIfErrored(final Class<? extends Protocol> protocolClass, @Nullable final Throwable throwable) {
|
||||
if (throwable != null) {
|
||||
Via.getPlatform().getLogger().log(Level.SEVERE, "Error during loading of " + protocolClass.getSimpleName(), throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -338,7 +338,10 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
|
||||
final ProtocolInfo protocolInfo = user().getProtocolInfo();
|
||||
final List<Protocol> protocols = protocolInfo.getPipeline().pipes(protocolClass, skipCurrentPipeline, direction);
|
||||
apply(direction, protocolInfo.getState(direction), protocols);
|
||||
// Use the packet's own state if known to avoid issues with stale tracked connection state
|
||||
// (e.g. a previous protocol in the pipeline already having changed serverState to PLAY while still processing FINISH_CONFIGURATION)
|
||||
final State state = this.packetType != null ? this.packetType.state() : protocolInfo.getState(direction);
|
||||
apply(direction, state, protocols);
|
||||
final ByteBuf output = allocateOutputBuffer();
|
||||
try {
|
||||
writeToBuffer(output);
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration;
|
||||
|
||||
public enum PacketBound {
|
||||
ADDED_AT_MIN,
|
||||
REMOVED_AT_MAX
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.protocol.version.VersionType;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations.RegistrationAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class RegistrationBuilder {
|
||||
private final List<VersionedTemplateGroup> groups = new ArrayList<>();
|
||||
private final SharedRegistrations registrations;
|
||||
private VersionType versionType;
|
||||
|
||||
RegistrationBuilder(final SharedRegistrations registrations) {
|
||||
this.registrations = registrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a registration for an open-ended version range.
|
||||
*
|
||||
* @param min minimum version, inclusive
|
||||
* @param action registration action
|
||||
* @return this
|
||||
*/
|
||||
public RegistrationBuilder since(final ProtocolVersion min, final RegistrationAction<?, ?> action) {
|
||||
checkVersionType(min);
|
||||
groups.add(new VersionedTemplateGroup(action, min, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a registration for a version range.
|
||||
*
|
||||
* @param min minimum version, inclusive
|
||||
* @param max maximum version, exclusive
|
||||
* @param action registration action
|
||||
* @return this
|
||||
*/
|
||||
public RegistrationBuilder range(final ProtocolVersion min, final ProtocolVersion max, final RegistrationAction<?, ?> action) {
|
||||
checkVersionType(min);
|
||||
checkVersionType(max);
|
||||
groups.add(new VersionedTemplateGroup(action, min, max));
|
||||
return this;
|
||||
}
|
||||
|
||||
public <CU extends ClientboundPacketType, SU extends ServerboundPacketType> RegistrationBuilder ranges(
|
||||
final ProtocolVersion min, final Consumer<RangesBuilder<CU, SU>> consumer
|
||||
) {
|
||||
consumer.accept(new RangesBuilder<>(min));
|
||||
return this;
|
||||
}
|
||||
|
||||
public <CU extends ClientboundPacketType, SU extends ServerboundPacketType, R> RegistrationBuilder ranges(
|
||||
final Function<RegistrationContext<CU, SU>, R> adapter, final ProtocolVersion min,
|
||||
final Consumer<TypedRangesBuilder<CU, SU, R>> consumer
|
||||
) {
|
||||
consumer.accept(new TypedRangesBuilder<>(adapter, min));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void register() {
|
||||
registrations.register(versionType, groups);
|
||||
}
|
||||
|
||||
private void checkVersionType(final ProtocolVersion version) {
|
||||
if (versionType == null) {
|
||||
versionType = version.getVersionType();
|
||||
} else if (versionType != version.getVersionType()) {
|
||||
throw new IllegalArgumentException("Cannot mix different version types in the same registration builder");
|
||||
}
|
||||
}
|
||||
|
||||
public class RangesBuilder<CU extends ClientboundPacketType, SU extends ServerboundPacketType> {
|
||||
private ProtocolVersion currentMin;
|
||||
private boolean completed;
|
||||
|
||||
private RangesBuilder(final ProtocolVersion min) {
|
||||
this.currentMin = min;
|
||||
}
|
||||
|
||||
public RangesBuilder<CU, SU> to(final ProtocolVersion max, final RegistrationAction<CU, SU> action) {
|
||||
Preconditions.checkState(!completed, "Range chain already completed");
|
||||
RegistrationBuilder.this.range(currentMin, max, action);
|
||||
currentMin = max;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RegistrationBuilder since(final RegistrationAction<CU, SU> action) {
|
||||
Preconditions.checkState(!completed, "Range chain already completed");
|
||||
completed = true;
|
||||
return RegistrationBuilder.this.since(currentMin, action);
|
||||
}
|
||||
}
|
||||
|
||||
public final class TypedRangesBuilder<CU extends ClientboundPacketType, SU extends ServerboundPacketType, R> extends RangesBuilder<CU, SU> {
|
||||
private final Function<RegistrationContext<CU, SU>, R> adapter;
|
||||
|
||||
private TypedRangesBuilder(final Function<RegistrationContext<CU, SU>, R> adapter, final ProtocolVersion min) {
|
||||
super(min);
|
||||
this.adapter = adapter;
|
||||
}
|
||||
|
||||
public TypedRangesBuilder<CU, SU, R> to(final ProtocolVersion max, final TypedRegistrationAction<CU, SU, R> action) {
|
||||
to(max, wrapAction(action));
|
||||
return this;
|
||||
}
|
||||
|
||||
public TypedRangesBuilder<CU, SU, R> since(final TypedRegistrationAction<CU, SU, R> action) {
|
||||
since(wrapAction(action));
|
||||
return this;
|
||||
}
|
||||
|
||||
private RegistrationAction<CU, SU> wrapAction(final TypedRegistrationAction<CU, SU, R> action) {
|
||||
return ctx -> {
|
||||
final R rewriter = adapter.apply(ctx);
|
||||
if (rewriter != null) {
|
||||
action.accept(ctx, rewriter);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface TypedRegistrationAction<CU extends ClientboundPacketType, SU extends ServerboundPacketType, R> {
|
||||
|
||||
void accept(RegistrationContext<CU, SU> ctx, R r);
|
||||
}
|
||||
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import java.util.function.Consumer;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record RegistrationContext<CU extends ClientboundPacketType, SU extends ServerboundPacketType>(
|
||||
AbstractProtocol<CU, ?, ?, SU> protocol,
|
||||
ProtocolVersion min,
|
||||
@Nullable ProtocolVersion max
|
||||
) {
|
||||
|
||||
public <P extends AbstractProtocol<CU, ?, ?, SU>> P protocol(@SuppressWarnings("unused") final Class<P> protocolClass) {
|
||||
//noinspection unchecked
|
||||
return (P) protocol;
|
||||
}
|
||||
|
||||
public <P extends AbstractProtocol<CU, ?, ?, SU>> P castProtocol() {
|
||||
//noinspection unchecked
|
||||
return (P) protocol;
|
||||
}
|
||||
|
||||
public void clientbound(final ClientboundPacketType type, final Consumer<CU> action) {
|
||||
action.accept(clientboundPacketType(type));
|
||||
}
|
||||
|
||||
public void clientbound(final ClientboundPacketType type, final Consumer<CU> action, final PacketBound... markers) {
|
||||
if (!shouldSkip(markers)) {
|
||||
action.accept(clientboundPacketType(type));
|
||||
}
|
||||
}
|
||||
|
||||
public void clientboundHandler(final ClientboundPacketType type, final PacketHandler handler) {
|
||||
protocol.registerClientbound(clientboundPacketType(type), handler);
|
||||
}
|
||||
|
||||
public void clientboundHandler(final ClientboundPacketType type, final PacketHandler handler, final PacketBound... markers) {
|
||||
if (!shouldSkip(markers)) {
|
||||
protocol.registerClientbound(clientboundPacketType(type), handler);
|
||||
}
|
||||
}
|
||||
|
||||
public void serverbound(final ServerboundPacketType type, final Consumer<SU> action) {
|
||||
action.accept(serverboundPacketType(type));
|
||||
}
|
||||
|
||||
public void serverbound(final ServerboundPacketType type, final Consumer<SU> action, final PacketBound... markers) {
|
||||
if (!shouldSkip(markers)) {
|
||||
action.accept(serverboundPacketType(type));
|
||||
}
|
||||
}
|
||||
|
||||
public void serverboundHandler(final ServerboundPacketType type, final PacketHandler handler) {
|
||||
protocol.registerServerbound(serverboundPacketType(type), handler);
|
||||
}
|
||||
|
||||
public void serverboundHandler(final ServerboundPacketType type, final PacketHandler handler, final PacketBound... markers) {
|
||||
if (!shouldSkip(markers)) {
|
||||
protocol.registerServerbound(serverboundPacketType(type), handler);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldSkip(final PacketBound... markers) {
|
||||
if (markers.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final ProtocolVersion serverVersion = protocol.getServerVersion();
|
||||
final ProtocolVersion clientVersion = protocol.getClientVersion();
|
||||
final ProtocolVersion lowerVersion = serverVersion.olderThan(clientVersion) ? serverVersion : clientVersion;
|
||||
final ProtocolVersion higherVersion = serverVersion.newerThan(clientVersion) ? serverVersion : clientVersion;
|
||||
for (final PacketBound marker : markers) {
|
||||
switch (marker) {
|
||||
case ADDED_AT_MIN -> {
|
||||
if (lowerVersion.olderThan(min)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
case REMOVED_AT_MAX -> {
|
||||
Preconditions.checkArgument(max != null, "Cannot use REMOVED_AT_MAX in an open-ended range");
|
||||
if (higherVersion.newerThanOrEqualTo(max)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public SU serverboundPacketType(final ServerboundPacketType genericPacketType) {
|
||||
final SU type = protocol.getPacketTypesProvider().unmappedServerboundType(genericPacketType.state(), genericPacketType.getName());
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Could not find serverbound packet type for " + genericPacketType.state() + " " + genericPacketType.getName());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public CU clientboundPacketType(final ClientboundPacketType genericPacketType) {
|
||||
final CU type = protocol.getPacketTypesProvider().unmappedClientboundType(genericPacketType.state(), genericPacketType.getName());
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Could not find clientbound packet type for " + genericPacketType.state() + " " + genericPacketType.getName() + " in " + protocol.getClass().getSimpleName());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.protocol.version.VersionType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Central registry for shared packet registrations that are automatically applied
|
||||
* to protocols based on their version range.
|
||||
* <p>
|
||||
* Registrations are done BEFORE registerPackets in {@link AbstractProtocol}.
|
||||
*/
|
||||
public final class SharedRegistrations {
|
||||
private static final SharedRegistrations DEFAULT_REGISTRATIONS = new SharedRegistrations();
|
||||
|
||||
private final EnumMap<VersionType, List<VersionedTemplateGroup>> versionedTemplates = new EnumMap<>(VersionType.class);
|
||||
|
||||
/**
|
||||
* Returns the default ViaVersion registration set.
|
||||
*/
|
||||
public static SharedRegistrations defaultRegistrations() {
|
||||
return DEFAULT_REGISTRATIONS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an independent shared registration set that external projects can populate and apply.
|
||||
*/
|
||||
public static SharedRegistrations create() {
|
||||
return new SharedRegistrations();
|
||||
}
|
||||
|
||||
public RegistrationBuilder registrations() {
|
||||
return new RegistrationBuilder(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies all shared registrations whose version range matches the given protocol.
|
||||
*
|
||||
* @param protocol the protocol to apply shared registrations to
|
||||
*/
|
||||
public void applyMatching(final AbstractProtocol<?, ?, ?, ?> protocol) {
|
||||
if (protocol.isBaseProtocol()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ProtocolVersion version = protocol.getServerVersion();
|
||||
if (version.getVersionType() != protocol.getClientVersion().getVersionType()) {
|
||||
// Built on continuous version ranges
|
||||
return;
|
||||
}
|
||||
|
||||
final List<VersionedTemplateGroup> groups = versionedTemplates.get(version.getVersionType());
|
||||
if (groups == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final VersionedTemplateGroup group : groups) {
|
||||
if (group.min().newerThan(version)) { // TODO binary search?
|
||||
// Sorted by the minimum, so we can stop early if we're out
|
||||
break;
|
||||
}
|
||||
|
||||
if (group.max() != null && version.newerThanOrEqualTo(group.max())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final RegistrationContext<?, ?> context = new RegistrationContext<>(protocol, group.min(), group.max());
|
||||
//noinspection unchecked,rawtypes
|
||||
((RegistrationAction) group.action()).accept(context);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RegistrationAction<CU extends ClientboundPacketType, SU extends ServerboundPacketType> {
|
||||
|
||||
void accept(RegistrationContext<CU, SU> context);
|
||||
}
|
||||
|
||||
void register(final VersionType versionType, final List<VersionedTemplateGroup> toAdd) {
|
||||
final List<VersionedTemplateGroup> groups = versionedTemplates.computeIfAbsent(versionType, $ -> new ArrayList<>());
|
||||
groups.addAll(toAdd);
|
||||
groups.sort(Comparator.comparing(VersionedTemplateGroup::min, Comparator.nullsFirst(Comparator.naturalOrder())));
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations.RegistrationAction;
|
||||
|
||||
record VersionedTemplateGroup(
|
||||
RegistrationAction<?, ?> action,
|
||||
ProtocolVersion min,
|
||||
ProtocolVersion max
|
||||
) {
|
||||
|
||||
public boolean contains(final ProtocolVersion version) {
|
||||
return version.newerThanOrEqualTo(min) && (max == null || version.olderThan(max));
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_14_3to1_14_4.packet.ClientboundPackets1_14_4;
|
||||
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2;
|
||||
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18;
|
||||
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
|
||||
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
final class BlockRegistrations {
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerBlockPackets1_13(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
|
||||
common1_13(ctx, br);
|
||||
ctx.clientbound(ClientboundPackets1_13.CHUNK_BLOCKS_UPDATE, br::registerChunkBlocksUpdate);
|
||||
}
|
||||
|
||||
private static <CU extends ClientboundPacketType> void common1_13(RegistrationContext<CU, ?> ctx, BlockRewriter<CU> br) {
|
||||
ctx.clientbound(ClientboundPackets1_13.BLOCK_EVENT, br::registerBlockEvent);
|
||||
ctx.clientbound(ClientboundPackets1_13.BLOCK_UPDATE, br::registerBlockUpdate);
|
||||
ctx.clientbound(ClientboundPackets1_13.LEVEL_EVENT, br::registerLevelEvent1_13);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerBlockPackets1_14_4(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
|
||||
common1_13(ctx, br);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.CHUNK_BLOCKS_UPDATE, br::registerChunkBlocksUpdate, PacketBound.REMOVED_AT_MAX);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.BLOCK_BREAK_ACK, br::registerBlockBreakAck, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerBlockPackets1_16_2(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
|
||||
common1_13(ctx, br);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.BLOCK_BREAK_ACK, br::registerBlockBreakAck);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerBlockPackets1_18(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
|
||||
common1_13(ctx, br);
|
||||
ctx.clientbound(ClientboundPackets1_18.BLOCK_BREAK_ACK, br::registerBlockBreakAck, PacketBound.REMOVED_AT_MAX);
|
||||
ctx.clientbound(ClientboundPackets1_18.LEVEL_CHUNK_WITH_LIGHT, br::registerLevelChunk1_18, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_18.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate);
|
||||
ctx.clientbound(ClientboundPackets1_18.BLOCK_ENTITY_DATA, br::registerBlockEntityData1_18);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerBlockPackets1_19(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
|
||||
common1_19(ctx, br);
|
||||
ctx.clientbound(ClientboundPackets1_19.LEVEL_EVENT, br::registerLevelEvent1_13);
|
||||
ctx.clientbound(ClientboundPackets1_19.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate);
|
||||
}
|
||||
|
||||
private static <CU extends ClientboundPacketType> void common1_19(RegistrationContext<CU, ?> ctx, BlockRewriter<CU> br) {
|
||||
ctx.clientbound(ClientboundPackets1_19.BLOCK_EVENT, br::registerBlockEvent);
|
||||
ctx.clientbound(ClientboundPackets1_19.BLOCK_UPDATE, br::registerBlockUpdate);
|
||||
ctx.clientbound(ClientboundPackets1_19.LEVEL_CHUNK_WITH_LIGHT, br::registerLevelChunk1_18);
|
||||
ctx.clientbound(ClientboundPackets1_19.BLOCK_ENTITY_DATA, br::registerBlockEntityData1_18);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerBlockPackets1_20(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
|
||||
common1_19(ctx, br);
|
||||
ctx.clientbound(ClientboundPackets1_19_4.LEVEL_EVENT, br::registerLevelEvent1_13);
|
||||
ctx.clientbound(ClientboundPackets1_19_4.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate1_20);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerBlockPackets1_21(final RegistrationContext<CU, ?> ctx, final BlockRewriter<CU> br) {
|
||||
common1_19(ctx, br);
|
||||
ctx.clientbound(ClientboundPackets1_21.LEVEL_EVENT, br::registerLevelEvent1_21);
|
||||
ctx.clientbound(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE, br::registerSectionBlocksUpdate1_20);
|
||||
}
|
||||
|
||||
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> BlockRewriter<CU> block(final RegistrationContext<CU, SU> ctx) {
|
||||
return ctx.protocol().getBlockRewriter();
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.SharedRegistrations;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.def.base.ConfigurationRegistrations;
|
||||
|
||||
public final class DefaultRegistrations {
|
||||
|
||||
public static void apply() {
|
||||
SharedRegistrations.defaultRegistrations().registrations()
|
||||
.ranges(EntityRegistrations::entity, ProtocolVersion.v1_13, b -> b
|
||||
.to(ProtocolVersion.v1_14_4, EntityRegistrations::registerEntityPackets1_13)
|
||||
.to(ProtocolVersion.v1_16_2, EntityRegistrations::registerEntityPackets1_14_4)
|
||||
.to(ProtocolVersion.v1_17_1, EntityRegistrations::registerEntityPackets1_16_2)
|
||||
.to(ProtocolVersion.v1_19, EntityRegistrations::registerEntityPackets1_17_1)
|
||||
.to(ProtocolVersion.v1_20_5, EntityRegistrations::registerEntityPackets1_19)
|
||||
.to(ProtocolVersion.v1_21_4, EntityRegistrations::registerEntityPackets1_20_5)
|
||||
.to(ProtocolVersion.v1_21_9, EntityRegistrations::registerEntityPackets1_21_4)
|
||||
.since(EntityRegistrations::registerEntityPackets1_21_9)
|
||||
)
|
||||
|
||||
.ranges(ItemRegistrations::item, ProtocolVersion.v1_13, b -> b
|
||||
.to(ProtocolVersion.v1_14, ItemRegistrations::registerItemPackets1_13)
|
||||
.to(ProtocolVersion.v1_14_4, ItemRegistrations::registerItemPackets1_14)
|
||||
.to(ProtocolVersion.v1_16, ItemRegistrations::registerItemPackets1_14_4)
|
||||
.to(ProtocolVersion.v1_17_1, ItemRegistrations::registerItemPackets1_16)
|
||||
.to(ProtocolVersion.v1_19_1, ItemRegistrations::registerItemPackets1_17_1)
|
||||
.to(ProtocolVersion.v1_20_3, ItemRegistrations::registerItemPackets1_19_1)
|
||||
.to(ProtocolVersion.v1_20_5, ItemRegistrations::registerItemPackets1_20_3)
|
||||
.to(ProtocolVersion.v1_21, ItemRegistrations::registerItemPackets1_20_5)
|
||||
.to(ProtocolVersion.v1_21_2, ItemRegistrations::registerItemPackets1_21)
|
||||
.to(ProtocolVersion.v1_21_5, ItemRegistrations::registerItemPackets1_21_2)
|
||||
)
|
||||
.ranges(ItemRegistrations::structuredItem, ProtocolVersion.v1_21_5, b -> b
|
||||
.to(ProtocolVersion.v1_21_6, ItemRegistrations::registerItemPackets1_21_5)
|
||||
.since(ItemRegistrations::registerItemPackets1_21_6)
|
||||
)
|
||||
|
||||
.ranges(BlockRegistrations::block, ProtocolVersion.v1_13, steps -> steps
|
||||
.to(ProtocolVersion.v1_14_4, BlockRegistrations::registerBlockPackets1_13)
|
||||
.to(ProtocolVersion.v1_16_2, BlockRegistrations::registerBlockPackets1_14_4)
|
||||
.to(ProtocolVersion.v1_18, BlockRegistrations::registerBlockPackets1_16_2)
|
||||
.to(ProtocolVersion.v1_19, BlockRegistrations::registerBlockPackets1_18)
|
||||
.to(ProtocolVersion.v1_20, BlockRegistrations::registerBlockPackets1_19)
|
||||
.to(ProtocolVersion.v1_21, BlockRegistrations::registerBlockPackets1_20)
|
||||
.since(BlockRegistrations::registerBlockPackets1_21)
|
||||
)
|
||||
|
||||
.ranges(ParticleRegistrations::particle, ProtocolVersion.v1_13, steps -> steps
|
||||
.to(ProtocolVersion.v1_15_2, ParticleRegistrations::registerParticlePackets1_13)
|
||||
.to(ProtocolVersion.v1_19, ParticleRegistrations::registerParticlePackets1_15_2)
|
||||
.to(ProtocolVersion.v1_20, ParticleRegistrations::registerParticlePackets1_19)
|
||||
.to(ProtocolVersion.v1_20_5, ParticleRegistrations::registerParticlePackets1_20)
|
||||
.to(ProtocolVersion.v1_21_2, ParticleRegistrations::registerParticlePackets1_20_5)
|
||||
.to(ProtocolVersion.v1_21_4, ParticleRegistrations::registerParticlePackets1_21_2)
|
||||
.to(ProtocolVersion.v1_21_9, ParticleRegistrations::registerParticlePackets1_21_4)
|
||||
.since(ParticleRegistrations::registerParticlePackets1_21_9)
|
||||
)
|
||||
|
||||
.ranges(TextComponentRegistrations::text, ProtocolVersion.v1_12_2, b -> b
|
||||
.to(ProtocolVersion.v1_14, TextComponentRegistrations::registerComponents1_12_2)
|
||||
.to(ProtocolVersion.v1_16_2, TextComponentRegistrations::registerComponents1_14)
|
||||
.to(ProtocolVersion.v1_17, TextComponentRegistrations::registerComponents1_16_2)
|
||||
.to(ProtocolVersion.v1_19, TextComponentRegistrations::registerComponents1_17)
|
||||
.to(ProtocolVersion.v1_20_3, TextComponentRegistrations::registerComponents1_19)
|
||||
.to(ProtocolVersion.v1_20_5, TextComponentRegistrations::registerComponents1_20_3)
|
||||
.to(ProtocolVersion.v1_21, TextComponentRegistrations::registerComponents1_20_5)
|
||||
.to(ProtocolVersion.v1_21_4, TextComponentRegistrations::registerComponents1_21)
|
||||
.to(ProtocolVersion.v1_21_5, TextComponentRegistrations::registerComponents1_21_4)
|
||||
)
|
||||
.ranges(TextComponentRegistrations::nbtText, ProtocolVersion.v1_21_5, b -> b
|
||||
.since(TextComponentRegistrations::registerComponents1_21_5)
|
||||
)
|
||||
|
||||
.ranges(ProtocolVersion.v1_17_1, sbeps -> sbeps
|
||||
.to(ProtocolVersion.v1_20_2, RegistryRegistrations::registerTags1_17_1)
|
||||
.since(RegistryRegistrations::registerTags1_20_2)
|
||||
)
|
||||
|
||||
.ranges(ProtocolVersion.v1_10, b -> b
|
||||
.to(ProtocolVersion.v1_14, RegistryRegistrations::registerSounds1_10)
|
||||
.to(ProtocolVersion.v1_19_3, RegistryRegistrations::registerSounds1_14)
|
||||
.since(RegistryRegistrations::registerSounds1_19_3)
|
||||
)
|
||||
|
||||
.since(ProtocolVersion.v1_13, RegistryRegistrations::registerStatistics1_13)
|
||||
.since(ProtocolVersion.v1_19, RegistryRegistrations::registerCommands1_19)
|
||||
.since(ProtocolVersion.v1_20_2, ConfigurationRegistrations::registerConfigurationStateSwitching)
|
||||
.since(ProtocolVersion.v1_21, RegistryRegistrations::registerRegistryData1_21)
|
||||
.since(ProtocolVersion.v1_21, RegistryRegistrations::registerAttributes1_21)
|
||||
.since(ProtocolVersion.v1_21_2, RegistryRegistrations::registerRecipePackets1_21_2)
|
||||
|
||||
.register();
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_14_3to1_14_4.packet.ClientboundPackets1_14_4;
|
||||
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
final class EntityRegistrations {
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_13(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
ctx.clientbound(ClientboundPackets1_13.REMOVE_ENTITIES, er::registerRemoveEntities);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_14_4(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
ctx.clientbound(ClientboundPackets1_14_4.REMOVE_ENTITIES, er::registerRemoveEntities);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.ADD_ENTITY, er::registerTrackerWithData);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.ADD_MOB, er::registerTracker);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_16_2(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
// remove_entities got temporarily changed to only take a single entity...
|
||||
ctx.clientbound(ClientboundPackets1_14_4.ADD_ENTITY, er::registerTrackerWithData);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.ADD_MOB, er::registerTracker);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_17_1(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
ctx.clientbound(ClientboundPackets1_14_4.REMOVE_ENTITIES, er::registerRemoveEntities);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.ADD_ENTITY, er::registerTrackerWithData);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.ADD_MOB, er::registerTracker, PacketBound.REMOVED_AT_MAX);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_19(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
ctx.clientbound(ClientboundPackets1_9.REMOVE_ENTITIES, er::registerRemoveEntities);
|
||||
ctx.clientbound(ClientboundPackets1_19.ADD_ENTITY, er::registerTrackerWithData1_19);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_20_5(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
common1_20_5(ctx, er);
|
||||
ctx.clientbound(ClientboundPackets1_19.ADD_ENTITY, er::registerTrackerWithData1_19);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_21_4(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
common1_20_5(ctx, er);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.ADD_ENTITY, er::registerTrackerWithData1_19);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerEntityPackets1_21_9(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
common1_20_5(ctx, er);
|
||||
ctx.clientbound(ClientboundPackets1_21_9.ADD_ENTITY, er::registerTrackerWithData1_21_9);
|
||||
}
|
||||
|
||||
private static <CU extends ClientboundPacketType> void common1_20_5(final RegistrationContext<CU, ?> ctx, final EntityRewriter<CU, ?> er) {
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_ENTITY_DATA, er::registerSetEntityData);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.REMOVE_ENTITIES, er::registerRemoveEntities);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.LOGIN, er::registerLogin1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.RESPAWN, er::registerRespawn1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.GAME_EVENT, er::registerGameEvent);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_ABILITIES, er::registerPlayerAbilities);
|
||||
}
|
||||
|
||||
|
||||
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> EntityRewriter<CU, ?> entity(final RegistrationContext<CU, SU> ctx) {
|
||||
return (EntityRewriter<CU, ?>) ctx.protocol().getEntityRewriter();
|
||||
}
|
||||
}
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ServerboundPackets1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
|
||||
import com.viaversion.viaversion.protocols.v1_14_3to1_14_4.packet.ClientboundPackets1_14_4;
|
||||
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
|
||||
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ServerboundPackets1_17;
|
||||
import com.viaversion.viaversion.protocols.v1_17to1_17_1.packet.ClientboundPackets1_17_1;
|
||||
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ServerboundPackets1_19_3;
|
||||
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4;
|
||||
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPackets1_19_1;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPackets1_20_3;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ServerboundPackets1_20_3;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPackets1_21_5;
|
||||
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ServerboundPackets1_21_5;
|
||||
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundConfigurationPackets1_21_6;
|
||||
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ClientboundPackets1_21_6;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ServerboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.ItemRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
final class ItemRegistrations {
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_13(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
common1_13(ctx, ir);
|
||||
ctx.clientbound(ClientboundPackets1_13.SET_EQUIPPED_ITEM, ir::registerSetEquippedItem);
|
||||
}
|
||||
|
||||
private static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void common1_13(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_13.CONTAINER_SET_DATA, ir::registerContainerSetData);
|
||||
ctx.clientbound(ClientboundPackets1_13.CONTAINER_SET_SLOT, ir::registerSetSlot);
|
||||
ctx.clientbound(ClientboundPackets1_13.CONTAINER_SET_CONTENT, ir::registerSetContent);
|
||||
ctx.clientbound(ClientboundPackets1_13.UPDATE_ADVANCEMENTS, ir::registerAdvancements);
|
||||
ctx.clientbound(ClientboundPackets1_13.COOLDOWN, ir::registerCooldown);
|
||||
ctx.serverbound(ServerboundPackets1_13.CONTAINER_CLICK, ir::registerContainerClick);
|
||||
ctx.serverbound(ServerboundPackets1_13.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_14(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
common1_13(ctx, ir);
|
||||
ctx.clientbound(ClientboundPackets1_14.SET_EQUIPPED_ITEM, ir::registerSetEquippedItem);
|
||||
ctx.clientbound(ClientboundPackets1_14.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_14_4(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
common1_13(ctx, ir);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.SET_EQUIPPED_ITEM, ir::registerSetEquippedItem, PacketBound.REMOVED_AT_MAX);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_14_4.MERCHANT_OFFERS, ir::registerMerchantOffers1_14_4);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_16(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
common1_13(ctx, ir);
|
||||
ctx.clientbound(ClientboundPackets1_16.SET_EQUIPMENT, ir::registerSetEquipment, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_16.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_16.MERCHANT_OFFERS, ir::registerMerchantOffers1_14_4);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_17_1(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_17_1.CONTAINER_SET_DATA, ir::registerContainerSetData);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.UPDATE_ADVANCEMENTS, ir::registerAdvancements);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.COOLDOWN, ir::registerCooldown);
|
||||
ctx.serverbound(ServerboundPackets1_17.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
|
||||
ctx.serverbound(ServerboundPackets1_17.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.SET_EQUIPMENT, ir::registerSetEquipment);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.MERCHANT_OFFERS, ir::registerMerchantOffers1_14_4);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_19_1(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_19_1.CONTAINER_SET_DATA, ir::registerContainerSetData);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.UPDATE_ADVANCEMENTS, ir::registerAdvancements);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.COOLDOWN, ir::registerCooldown);
|
||||
ctx.serverbound(ServerboundPackets1_19_3.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
|
||||
ctx.serverbound(ServerboundPackets1_19_3.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.SET_EQUIPMENT, ir::registerSetEquipment);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.MERCHANT_OFFERS, ir::registerMerchantOffers1_19);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_20_3(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_DATA, ir::registerContainerSetData);
|
||||
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
|
||||
ctx.clientbound(ClientboundPackets1_20_3.COOLDOWN, ir::registerCooldown);
|
||||
ctx.serverbound(ServerboundPackets1_20_3.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
|
||||
ctx.serverbound(ServerboundPackets1_20_2.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_EQUIPMENT, ir::registerSetEquipment);
|
||||
ctx.clientbound(ClientboundPackets1_19_4.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_20_2.MERCHANT_OFFERS, ir::registerMerchantOffers1_19);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_20_5(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_20_3.CONTAINER_SET_DATA, ir::registerContainerSetData);
|
||||
registerItemPackets1_21(ctx, ir);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_21.CONTAINER_SET_SLOT, ir::registerSetSlot1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_21.CONTAINER_SET_CONTENT, ir::registerSetContent1_17_1);
|
||||
ctx.clientbound(ClientboundPackets1_21.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
|
||||
ctx.clientbound(ClientboundPackets1_21.COOLDOWN, ir::registerCooldown);
|
||||
ctx.serverbound(ServerboundPackets1_20_5.CONTAINER_CLICK, ir::registerContainerClick1_17_1);
|
||||
ctx.serverbound(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_21.SET_EQUIPMENT, ir::registerSetEquipment);
|
||||
ctx.clientbound(ClientboundPackets1_21.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_21.MERCHANT_OFFERS, ir::registerMerchantOffers1_20_5);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21_2(final RegistrationContext<CU, SU> ctx, final ItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_21_2.CONTAINER_SET_SLOT, ir::registerSetSlot1_21_2);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.CONTAINER_SET_CONTENT, ir::registerSetContent1_21_2);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.COOLDOWN, ir::registerCooldown1_21_2);
|
||||
ctx.serverbound(ServerboundPackets1_21_2.CONTAINER_CLICK, ir::registerContainerClick1_21_2);
|
||||
ctx.serverbound(ServerboundPackets1_21_2.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.SET_EQUIPMENT, ir::registerSetEquipment);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.MERCHANT_OFFERS, ir::registerMerchantOffers1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.SET_PLAYER_INVENTORY, ir::registerSetPlayerInventory, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, ir::registerSetCursorItem, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21_5(final RegistrationContext<CU, SU> ctx, final StructuredItemRewriter<CU, SU, ?> ir) {
|
||||
ctx.clientbound(ClientboundPackets1_21_5.CONTAINER_SET_SLOT, ir::registerSetSlot1_21_2);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.CONTAINER_SET_CONTENT, ir::registerSetContent1_21_2);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.UPDATE_ADVANCEMENTS, ir::registerAdvancements1_20_3);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.COOLDOWN, ir::registerCooldown1_21_2);
|
||||
ctx.serverbound(ServerboundPackets1_21_5.CONTAINER_CLICK, ir::registerContainerClick1_21_5);
|
||||
ctx.serverbound(ServerboundPackets1_21_5.SET_CREATIVE_MODE_SLOT, ir::registerSetCreativeModeSlot1_21_5);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.SET_EQUIPMENT, ir::registerSetEquipment);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.OPEN_SCREEN, ir::registerOpenScreen);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.MERCHANT_OFFERS, ir::registerMerchantOffers1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.SET_PLAYER_INVENTORY, ir::registerSetPlayerInventory);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.SET_CURSOR_ITEM, ir::registerSetCursorItem);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerItemPackets1_21_6(final RegistrationContext<CU, SU> ctx, final StructuredItemRewriter<CU, SU, ?> ir) {
|
||||
registerItemPackets1_21_5(ctx, ir);
|
||||
ctx.clientbound(ClientboundPackets1_21_6.SHOW_DIALOG, ir::registerShowDialog, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundConfigurationPackets1_21_6.SHOW_DIALOG, ir::registerShowDialogDirect, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
|
||||
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ItemRewriter<CU, SU, ?> item(final RegistrationContext<CU, SU> ctx) {
|
||||
return (ItemRewriter<CU, SU, ?>) ctx.protocol().getItemRewriter();
|
||||
}
|
||||
|
||||
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> StructuredItemRewriter<CU, SU, ?> structuredItem(final RegistrationContext<CU, SU> ctx) {
|
||||
return (StructuredItemRewriter<CU, SU, ?>) ctx.protocol().getItemRewriter();
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def;
|
||||
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15;
|
||||
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundPackets1_21_9;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.ParticleRewriter;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
final class ParticleRegistrations {
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_13(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_13.LEVEL_PARTICLES, type -> pr.registerLevelParticles1_13(type, Types.FLOAT));
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_15_2(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_15.LEVEL_PARTICLES, type -> pr.registerLevelParticles1_13(type, Types.DOUBLE));
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_19(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_19.LEVEL_PARTICLES, pr::registerLevelParticles1_19);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_20(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_19.LEVEL_PARTICLES, pr::registerLevelParticles1_19);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_20_5(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_20_5.LEVEL_PARTICLES, pr::registerLevelParticles1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.EXPLODE, pr::registerExplode1_20_5);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_21_2(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_21_2.LEVEL_PARTICLES, pr::registerLevelParticles1_20_5);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.EXPLODE, pr::registerExplode1_21_2);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_21_4(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_21_2.LEVEL_PARTICLES, pr::registerLevelParticles1_21_4);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.EXPLODE, pr::registerExplode1_21_2);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerParticlePackets1_21_9(final RegistrationContext<CU, ?> ctx, final ParticleRewriter<CU> pr) {
|
||||
ctx.clientbound(ClientboundPackets1_21_9.LEVEL_PARTICLES, pr::registerLevelParticles1_21_4);
|
||||
ctx.clientbound(ClientboundPackets1_21_9.EXPLODE, pr::registerExplode1_21_9);
|
||||
}
|
||||
|
||||
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ParticleRewriter<CU> particle(final RegistrationContext<CU, SU> ctx) {
|
||||
return (ParticleRewriter<CU>) ctx.protocol().getParticleRewriter();
|
||||
}
|
||||
}
|
||||
+105
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def;
|
||||
|
||||
import com.viaversion.viaversion.api.data.Mappings;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14;
|
||||
import com.viaversion.viaversion.protocols.v1_17to1_17_1.packet.ClientboundPackets1_17_1;
|
||||
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3;
|
||||
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.rewriter.CommandRewriter1_19_4;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundConfigurationPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
|
||||
import com.viaversion.viaversion.rewriter.AttributeRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
|
||||
import com.viaversion.viaversion.rewriter.TagRewriter;
|
||||
|
||||
final class RegistryRegistrations {
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerTags1_17_1(final RegistrationContext<CU, ?> ctx) {
|
||||
if (ctx.protocol().getTagRewriter() instanceof final TagRewriter tagRewriter) {
|
||||
ctx.clientbound(ClientboundPackets1_17_1.UPDATE_TAGS, tagRewriter::registerGeneric);
|
||||
}
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerTags1_20_2(final RegistrationContext<CU, ?> ctx) {
|
||||
if (ctx.protocol().getTagRewriter() instanceof final TagRewriter tagRewriter) {
|
||||
ctx.clientbound(ClientboundPackets1_20_2.UPDATE_TAGS, tagRewriter::registerGeneric);
|
||||
ctx.clientbound(ClientboundConfigurationPackets1_20_2.UPDATE_TAGS, tagRewriter::registerGeneric, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerRegistryData1_21(final RegistrationContext<CU, ?> ctx) {
|
||||
if (ctx.protocol().getRegistryDataRewriter() == null) return;
|
||||
ctx.clientboundHandler(ClientboundConfigurationPackets1_21.REGISTRY_DATA, ctx.protocol().getRegistryDataRewriter()::handle);
|
||||
}
|
||||
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerRecipePackets1_21_2(final RegistrationContext<CU, ?> ctx) {
|
||||
final RecipeDisplayRewriter<CU> rr = ctx.protocol().getRecipeRewriter();
|
||||
if (rr == null) return;
|
||||
ctx.clientbound(ClientboundPackets1_21_2.UPDATE_RECIPES, rr::registerUpdateRecipes);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.RECIPE_BOOK_ADD, rr::registerRecipeBookAdd, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.PLACE_GHOST_RECIPE, rr::registerPlaceGhostRecipe);
|
||||
}
|
||||
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerStatistics1_13(final RegistrationContext<CU, ?> ctx) {
|
||||
ctx.clientbound(ClientboundPackets1_13.AWARD_STATS, new StatisticsRewriter<>(ctx.protocol())::register);
|
||||
}
|
||||
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerSounds1_10(final RegistrationContext<CU, ?> ctx) {
|
||||
ctx.clientbound(ClientboundPackets1_9_3.SOUND, new SoundRewriter<>(ctx.protocol())::registerSound);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerSounds1_14(final RegistrationContext<CU, ?> ctx) {
|
||||
final SoundRewriter<CU> sr = new SoundRewriter<>(ctx.protocol());
|
||||
ctx.clientbound(ClientboundPackets1_14.SOUND, sr::registerSound);
|
||||
ctx.clientbound(ClientboundPackets1_14.SOUND_ENTITY, sr::registerSound, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerSounds1_19_3(final RegistrationContext<CU, ?> ctx) {
|
||||
final SoundRewriter<CU> sr = new SoundRewriter<>(ctx.protocol());
|
||||
ctx.clientbound(ClientboundPackets1_19_3.SOUND, sr::registerSound1_19_3);
|
||||
ctx.clientbound(ClientboundPackets1_19_3.SOUND_ENTITY, sr::registerSound1_19_3);
|
||||
}
|
||||
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerCommands1_19(final RegistrationContext<CU, ?> ctx) {
|
||||
if ((ctx.protocol().getMappingData() != null && !Mappings.isIntIdIdentity(ctx.protocol().getMappingData().getArgumentTypeMappings()))
|
||||
|| ctx.protocol().getRegistryDataRewriter() != null) {
|
||||
ctx.clientbound(ClientboundPackets1_19_3.COMMANDS, new CommandRewriter1_19_4<>(ctx.protocol())::registerDeclareCommands1_19);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerAttributes1_21(final RegistrationContext<CU, ?> ctx) {
|
||||
ctx.clientbound(ClientboundPackets1_21.UPDATE_ATTRIBUTES, new AttributeRewriter<>(ctx.protocol())::register1_21);
|
||||
}
|
||||
}
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.ChatType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
|
||||
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
|
||||
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16;
|
||||
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2;
|
||||
import com.viaversion.viaversion.protocols.v1_17to1_17_1.packet.ClientboundPackets1_17_1;
|
||||
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19;
|
||||
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPackets1_19_1;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundConfigurationPackets1_20_3;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.packet.ClientboundPackets1_20_3;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.packet.ClientboundPackets1_21_5;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.packet.ClientboundPackets1_21_2;
|
||||
import com.viaversion.viaversion.rewriter.text.ComponentRewriterBase;
|
||||
import com.viaversion.viaversion.rewriter.text.JsonNBTComponentRewriter;
|
||||
import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
final class TextComponentRegistrations {
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_12_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
ctx.clientbound(ClientboundPackets1_12_1.CHAT, cr::registerComponentPacket);
|
||||
registerCombatAndTitle1_12_2(ctx, cr);
|
||||
registerComponentsFrom1_12_2(ctx, cr);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_14(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
ctx.clientbound(ClientboundPackets1_12_1.CHAT, cr::registerComponentPacket);
|
||||
registerCombatAndTitle1_12_2(ctx, cr);
|
||||
registerComponentsFrom1_12_2(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_16_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
ctx.clientbound(ClientboundPackets1_16.CHAT, cr::registerComponentPacket);
|
||||
registerComponentsFrom1_12_2(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
if (!(cr instanceof final JsonNBTComponentRewriter<CU> jcr)) return;
|
||||
ctx.clientbound(ClientboundPackets1_12_1.PLAYER_COMBAT, jcr::registerPlayerCombat, PacketBound.REMOVED_AT_MAX);
|
||||
ctx.clientbound(ClientboundPackets1_12_1.SET_TITLES, jcr::registerTitle, PacketBound.REMOVED_AT_MAX);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_17(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
ctx.clientbound(ClientboundPackets1_16.CHAT, cr::registerComponentPacket, PacketBound.REMOVED_AT_MAX);
|
||||
registerComponentsFrom1_12_2(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.SET_ACTION_BAR_TEXT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.SET_TITLE_TEXT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.SET_SUBTITLE_TEXT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
|
||||
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
|
||||
ctx.clientbound(ClientboundPackets1_17_1.PLAYER_COMBAT_KILL, jcr::registerPlayerCombatKill, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_19(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
registerComponentsFrom1_12_2(ctx, cr);
|
||||
registerActionBarTitleSubtitle1_17_1(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
|
||||
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
|
||||
ctx.clientbound(ClientboundPackets1_17_1.PLAYER_COMBAT_KILL, jcr::registerPlayerCombatKill);
|
||||
}
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
ctx.clientbound(ClientboundPackets1_19.SYSTEM_CHAT, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
|
||||
ctx.clientbound(ClientboundPackets1_19.SERVER_DATA, cr::registerComponentPacket, PacketBound.ADDED_AT_MIN);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_20_3(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
registerComponentsFrom1_12_2(ctx, cr);
|
||||
registerActionBarTitleSubtitle1_17_1(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_16_2.SET_OBJECTIVE, cr::registerSetObjective);
|
||||
ctx.clientbound(ClientboundPackets1_19_1.SYSTEM_CHAT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundConfigurationPackets1_20_3.DISCONNECT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_3.DISGUISED_CHAT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_3.SET_SCORE, cr::registerSetScore1_20_3);
|
||||
ctx.clientbound(ClientboundPackets1_20_3.PLAYER_COMBAT_KILL, cr::registerPlayerCombatKill1_20);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
ctx.clientbound(ClientboundPackets1_19.SERVER_DATA, cr::registerComponentPacket);
|
||||
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
|
||||
ctx.clientbound(ClientboundPackets1_20_3.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, Types.VAR_INT));
|
||||
ctx.clientbound(ClientboundPackets1_20_3.PLAYER_INFO_UPDATE, jcr::registerPlayerInfoUpdate1_20_3);
|
||||
}
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerCombatAndTitle1_12_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
if (!(cr instanceof final JsonNBTComponentRewriter<CU> jcr)) return;
|
||||
ctx.clientbound(ClientboundPackets1_12_1.PLAYER_COMBAT, jcr::registerPlayerCombat);
|
||||
ctx.clientbound(ClientboundPackets1_12_1.SET_TITLES, jcr::registerTitle);
|
||||
}
|
||||
|
||||
private static <CU extends ClientboundPacketType> void registerComponentsFrom1_12_2(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
// not including set_score, player_info, update_advancements, and open_screen
|
||||
ctx.clientbound(ClientboundPackets1_12_1.BOSS_EVENT, cr::registerBossEvent);
|
||||
ctx.clientbound(ClientboundPackets1_12_1.DISCONNECT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_12_1.TAB_LIST, cr::registerTabList);
|
||||
cr.registerLoginDisconnect();
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerActionBarTitleSubtitle1_17_1(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
ctx.clientbound(ClientboundPackets1_17_1.SET_ACTION_BAR_TEXT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.SET_TITLE_TEXT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_17_1.SET_SUBTITLE_TEXT, cr::registerComponentPacket);
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_20_5(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
common1_20_5(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.DISGUISED_CHAT, cr::registerComponentPacket);
|
||||
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
|
||||
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, Types.VAR_INT));
|
||||
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_INFO_UPDATE, jcr::registerPlayerInfoUpdate1_20_3);
|
||||
}
|
||||
}
|
||||
|
||||
private static <CU extends ClientboundPacketType> void common1_20_5(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
ctx.clientbound(ClientboundConfigurationPackets1_20_5.DISCONNECT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.DISCONNECT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_ACTION_BAR_TEXT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_TITLE_TEXT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_SUBTITLE_TEXT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.BOSS_EVENT, cr::registerBossEvent);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.TAB_LIST, cr::registerTabList);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_OBJECTIVE, cr::registerSetObjective);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SET_SCORE, cr::registerSetScore1_20_3);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SYSTEM_CHAT, cr::registerComponentPacket);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.PLAYER_COMBAT_KILL, cr::registerPlayerCombatKill1_20);
|
||||
ctx.clientbound(ClientboundPackets1_20_5.SERVER_DATA, cr::registerComponentPacket);
|
||||
cr.registerLoginDisconnect();
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_21(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
common1_20_5(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_21.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
ctx.clientbound(ClientboundPackets1_21.DISGUISED_CHAT, cr::registerDisguisedChat);
|
||||
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
|
||||
ctx.clientbound(ClientboundPackets1_21.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, ChatType.TYPE));
|
||||
ctx.clientbound(ClientboundPackets1_21.PLAYER_INFO_UPDATE, jcr::registerPlayerInfoUpdate1_20_3);
|
||||
}
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_21_4(final RegistrationContext<CU, ?> ctx, final ComponentRewriterBase<CU> cr) {
|
||||
common1_20_5(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_13);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.DISGUISED_CHAT, cr::registerDisguisedChat);
|
||||
ctx.clientbound(ClientboundPackets1_21_2.PLAYER_INFO_UPDATE, cr::registerPlayerInfoUpdate1_21_4);
|
||||
if (cr instanceof final JsonNBTComponentRewriter<CU> jcr) {
|
||||
ctx.clientbound(ClientboundPackets1_21_2.PLAYER_CHAT, cu -> jcr.registerPlayerChat(cu, ChatType.TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
static <CU extends ClientboundPacketType> void registerComponents1_21_5(final RegistrationContext<CU, ?> ctx, final NBTComponentRewriter<CU> cr) {
|
||||
common1_20_5(ctx, cr);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.SET_PLAYER_TEAM, cr::registerSetPlayerTeam1_21_5);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.DISGUISED_CHAT, cr::registerDisguisedChat);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.PLAYER_INFO_UPDATE, cr::registerPlayerInfoUpdate1_21_4);
|
||||
ctx.clientbound(ClientboundPackets1_21_5.PLAYER_CHAT, cr::registerPlayerChat1_21_5);
|
||||
}
|
||||
|
||||
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> ComponentRewriterBase<CU> text(final RegistrationContext<CU, SU> ctx) {
|
||||
return (ComponentRewriterBase<CU>) ctx.protocol().getComponentRewriter();
|
||||
}
|
||||
|
||||
|
||||
static @Nullable <CU extends ClientboundPacketType, SU extends ServerboundPacketType> NBTComponentRewriter<CU> nbtText(final RegistrationContext<CU, SU> ctx) {
|
||||
return (NBTComponentRewriter<CU>) ctx.protocol().getComponentRewriter();
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2026 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocol.shared_registration.def.base;
|
||||
|
||||
import com.viaversion.viaversion.api.data.entity.EntityTracker;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.rewriter.RegistryDataRewriter;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.PacketBound;
|
||||
import com.viaversion.viaversion.protocol.shared_registration.RegistrationContext;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundConfigurationPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2;
|
||||
|
||||
public final class ConfigurationRegistrations {
|
||||
|
||||
public static <CU extends ClientboundPacketType, SU extends ServerboundPacketType> void registerConfigurationStateSwitching(final RegistrationContext<CU, SU> ctx) {
|
||||
ctx.serverbound(ServerboundPackets1_20_2.CONFIGURATION_ACKNOWLEDGED,
|
||||
packetType -> ctx.protocol().registerServerbound(packetType, wrapper -> wrapper.user().getProtocolInfo().setClientState(State.CONFIGURATION)),
|
||||
PacketBound.ADDED_AT_MIN
|
||||
);
|
||||
|
||||
ctx.clientbound(ClientboundPackets1_20_2.START_CONFIGURATION, packetType -> ctx.protocol().registerClientbound(packetType, wrapper -> {
|
||||
wrapper.user().getProtocolInfo().setServerState(State.CONFIGURATION);
|
||||
|
||||
// Mimic client behaviour by resetting tracked entities when configuration starts.
|
||||
final EntityTracker tracker = wrapper.user().getEntityTracker(ctx.protocol().getClass());
|
||||
if (tracker != null) {
|
||||
tracker.clear();
|
||||
}
|
||||
}), PacketBound.ADDED_AT_MIN);
|
||||
|
||||
ctx.serverbound(ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION,
|
||||
packetType -> ctx.protocol().registerServerbound(packetType, wrapper -> wrapper.user().getProtocolInfo().setClientState(State.PLAY)),
|
||||
PacketBound.ADDED_AT_MIN
|
||||
);
|
||||
|
||||
ctx.clientbound(ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION, packetType -> ctx.protocol().registerClientbound(packetType, wrapper -> {
|
||||
final RegistryDataRewriter registryDataRewriter = ctx.protocol().getRegistryDataRewriter();
|
||||
if (registryDataRewriter != null) {
|
||||
registryDataRewriter.sendMissingRegistries(wrapper.user());
|
||||
}
|
||||
wrapper.user().getProtocolInfo().setServerState(State.PLAY);
|
||||
}),
|
||||
PacketBound.ADDED_AT_MIN
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ import java.util.List;
|
||||
/**
|
||||
* Initial base protocol which is kept always in the pipeline.
|
||||
* <p>
|
||||
* State tracking for configuration state is done via {@link AbstractProtocol#registerConfigurationChangeHandlers()}
|
||||
* State tracking for configuration state is done via shared registrations.
|
||||
*/
|
||||
public class InitialBaseProtocol extends AbstractProtocol<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> {
|
||||
|
||||
|
||||
+9
-47
@@ -21,20 +21,10 @@ import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_4to1_21_5.rewriter.RecipeDisplayRewriter1_21_5;
|
||||
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
|
||||
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
import com.viaversion.viaversion.rewriter.block.BlockRewriter1_21_5;
|
||||
|
||||
// To replace if needed:
|
||||
// ChunkType26_1
|
||||
// RecipeDisplayRewriter
|
||||
final class BlockItemPacketRewriter99_1 extends StructuredItemRewriter<ClientboundPacket26_1, ServerboundPacket1_21_9, Protocol98_1To99_1> {
|
||||
|
||||
public BlockItemPacketRewriter99_1(final Protocol98_1To99_1 protocol) {
|
||||
@@ -43,37 +33,8 @@ final class BlockItemPacketRewriter99_1 extends StructuredItemRewriter<Clientbou
|
||||
|
||||
@Override
|
||||
public void registerPackets() {
|
||||
// Register block and block state id changes
|
||||
// Other places using block state id mappings: Spawn particle, entity data, entity spawn (falling blocks)
|
||||
// Tags and statistics use block (!) ids
|
||||
final BlockRewriter<ClientboundPacket26_1> blockRewriter = new BlockRewriter1_21_5<>(protocol);
|
||||
blockRewriter.registerBlockEvent(ClientboundPackets26_1.BLOCK_EVENT);
|
||||
blockRewriter.registerBlockUpdate(ClientboundPackets26_1.BLOCK_UPDATE);
|
||||
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets26_1.SECTION_BLOCKS_UPDATE);
|
||||
blockRewriter.registerLevelEvent1_21(ClientboundPackets26_1.LEVEL_EVENT, 2001);
|
||||
blockRewriter.registerLevelChunk1_19(ClientboundPackets26_1.LEVEL_CHUNK_WITH_LIGHT, ChunkType26_1::new);
|
||||
blockRewriter.registerBlockEntityData(ClientboundPackets26_1.BLOCK_ENTITY_DATA);
|
||||
|
||||
// Registers item id changes
|
||||
// Other places using item ids are: Entity data, tags, statistics, effect
|
||||
// registerOpenScreen(ClientboundPackets26_1.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
|
||||
registerSetCursorItem(ClientboundPackets26_1.SET_CURSOR_ITEM);
|
||||
registerSetPlayerInventory(ClientboundPackets26_1.SET_PLAYER_INVENTORY);
|
||||
registerCooldown1_21_2(ClientboundPackets26_1.COOLDOWN);
|
||||
registerSetContent1_21_2(ClientboundPackets26_1.CONTAINER_SET_CONTENT);
|
||||
registerSetSlot1_21_2(ClientboundPackets26_1.CONTAINER_SET_SLOT);
|
||||
registerAdvancements1_20_3(ClientboundPackets26_1.UPDATE_ADVANCEMENTS);
|
||||
registerSetEquipment(ClientboundPackets26_1.SET_EQUIPMENT);
|
||||
registerMerchantOffers1_20_5(ClientboundPackets26_1.MERCHANT_OFFERS);
|
||||
registerContainerClick1_21_5(ServerboundPackets1_21_6.CONTAINER_CLICK);
|
||||
registerSetCreativeModeSlot1_21_5(ServerboundPackets1_21_6.SET_CREATIVE_MODE_SLOT);
|
||||
|
||||
final RecipeDisplayRewriter<ClientboundPacket26_1> recipeRewriter = new RecipeDisplayRewriter1_21_5<>(protocol);
|
||||
recipeRewriter.registerUpdateRecipes(ClientboundPackets26_1.UPDATE_RECIPES);
|
||||
recipeRewriter.registerRecipeBookAdd(ClientboundPackets26_1.RECIPE_BOOK_ADD);
|
||||
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets26_1.PLACE_GHOST_RECIPE);
|
||||
// OR do this if serialization of recipes changed and override the relevant method
|
||||
// Add new serializers to RecipeDisplayRewriter, or extend the last one for changes
|
||||
// Common block, item, recipe, and entity registrations are handled by SharedRegistrations
|
||||
// If recipe serializers changed: add new serializers to RecipeDisplayRewriter, or extend the last one for changes
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,20 +45,21 @@ final class BlockItemPacketRewriter99_1 extends StructuredItemRewriter<Clientbou
|
||||
|
||||
@Override
|
||||
protected void handleItemDataComponentsToClient(final UserConnection connection, final Item item, final StructuredDataContainer container) {
|
||||
upgradeData(item, container);
|
||||
upgradeData(container);
|
||||
super.handleItemDataComponentsToClient(connection, item, container);
|
||||
}
|
||||
|
||||
public static void upgradeData(final Item item, final StructuredDataContainer container) { // public for VB
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleItemDataComponentsToServer(final UserConnection connection, final Item item, final StructuredDataContainer container) {
|
||||
downgradeData(item, container);
|
||||
downgradeData(container);
|
||||
super.handleItemDataComponentsToServer(connection, item, container);
|
||||
}
|
||||
|
||||
public static void downgradeData(final Item item, final StructuredDataContainer container) {
|
||||
// public for VB
|
||||
public static void upgradeData(final StructuredDataContainer container) {
|
||||
}
|
||||
|
||||
public static void downgradeData(final StructuredDataContainer container) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
-25
@@ -21,11 +21,9 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
|
||||
// Replace if needed
|
||||
// VersionedTypes
|
||||
// EntityTypes1_21_11
|
||||
final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_1, Protocol98_1To99_1> {
|
||||
|
||||
@@ -35,28 +33,19 @@ final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_
|
||||
|
||||
@Override
|
||||
public void registerPackets() {
|
||||
// Tracks entities, applies entity data rewrites registered below, untracks entities
|
||||
registerTrackerWithData1_21_9(ClientboundPackets26_1.ADD_ENTITY, EntityTypes1_21_11.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets26_1.SET_ENTITY_DATA);
|
||||
registerRemoveEntities(ClientboundPackets26_1.REMOVE_ENTITIES);
|
||||
registerPlayerAbilities(ClientboundPackets26_1.PLAYER_ABILITIES);
|
||||
registerGameEvent(ClientboundPackets26_1.GAME_EVENT);
|
||||
registerLogin1_20_5(ClientboundPackets26_1.LOGIN);
|
||||
registerRespawn1_20_5(ClientboundPackets26_1.RESPAWN);
|
||||
// Common entity registrations (including LOGIN, RESPAWN) are handled by SharedRegistrations.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerRewrites() {
|
||||
final EntityDataTypes26_1 entityDataTypes = protocol.mappedTypes().entityDataTypes();
|
||||
filter().mapDataType(entityDataTypes::byId);
|
||||
/* ... or something this if entity data classes changed
|
||||
filter().mapDataType(typeId -> {
|
||||
int id = typeId;
|
||||
if (id >= SomeAddedIndex) {
|
||||
id++;
|
||||
}
|
||||
return entityDataTypes.byId(id);
|
||||
});*/
|
||||
dataTypeMapper().register();
|
||||
/* ... or like this for additions and removals that are not at the very end
|
||||
dataTypeMapper()
|
||||
.added(entityDataTypes.catSoundVariant)
|
||||
.removed(entityDataTypes.cowSoundVariant)
|
||||
.skip(entityDataTypes.pigSoundVariant) // if neither removed nor added, but the value type has to be changed separately
|
||||
.register();*/
|
||||
|
||||
// Registers registry type id changes
|
||||
registerEntityDataTypeHandler(
|
||||
@@ -70,12 +59,6 @@ final class EntityPacketRewriter99_1 extends EntityRewriter<ClientboundPacket26_
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMappingDataLoaded() {
|
||||
// IF ENTITY TYPES CHANGED: Automatically map entity id changes AFTER entity ids have been loaded
|
||||
mapTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityType typeFromId(final int type) {
|
||||
return EntityTypes1_21_11.getTypeFromId(type);
|
||||
|
||||
+17
-63
@@ -21,27 +21,24 @@ import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.data.MappingDataBase;
|
||||
import com.viaversion.viaversion.api.minecraft.data.version.StructuredDataKeys1_21_11;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_21_11;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes26_1;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType26_1;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.version.VersionedTypes;
|
||||
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
import com.viaversion.viaversion.data.item.ItemHasherBase;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPacket26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_11to26_1.packet.ClientboundPackets26_1;
|
||||
import com.viaversion.viaversion.protocols.v1_21_5to1_21_6.packet.ServerboundPackets1_21_6;
|
||||
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ClientboundConfigurationPackets1_21_9;
|
||||
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundConfigurationPackets1_21_9;
|
||||
import com.viaversion.viaversion.protocols.v1_21_7to1_21_9.packet.ServerboundPacket1_21_9;
|
||||
import com.viaversion.viaversion.rewriter.AttributeRewriter;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ParticleRewriter;
|
||||
import com.viaversion.viaversion.rewriter.RegistryDataRewriter;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
|
||||
import com.viaversion.viaversion.rewriter.TagRewriter;
|
||||
import com.viaversion.viaversion.rewriter.block.BlockRewriter1_21_5;
|
||||
import com.viaversion.viaversion.rewriter.text.NBTComponentRewriter;
|
||||
|
||||
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
|
||||
@@ -49,14 +46,15 @@ import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
|
||||
// Placeholders to replace (in the entire package):
|
||||
// ClientboundPacket26_1
|
||||
// ServerboundPacket1_21_9
|
||||
// EntityDataTypes26_1 (MAPPED type)
|
||||
// VersionedTypes.V26_1
|
||||
// ChunkType26_1::new
|
||||
// 98.1, 99.1
|
||||
final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, ClientboundPacket26_1, ServerboundPacket1_21_9, ServerboundPacket1_21_9> {
|
||||
|
||||
public static final MappingData MAPPINGS = new MappingDataBase("98.1", "99.1");
|
||||
private final EntityPacketRewriter99_1 entityRewriter = new EntityPacketRewriter99_1(this);
|
||||
private final BlockItemPacketRewriter99_1 itemRewriter = new BlockItemPacketRewriter99_1(this);
|
||||
private final BlockRewriter<ClientboundPacket26_1> blockRewriter = new BlockRewriter1_21_5<>(this, ChunkType26_1::new);
|
||||
private final ParticleRewriter<ClientboundPacket26_1> particleRewriter = new ParticleRewriter<>(this);
|
||||
private final TagRewriter<ClientboundPacket26_1> tagRewriter = new TagRewriter<>(this);
|
||||
private final NBTComponentRewriter<ClientboundPacket26_1> componentRewriter = new ComponentRewriter99_1(this);
|
||||
@@ -71,40 +69,9 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
|
||||
protected void registerPackets() {
|
||||
super.registerPackets();
|
||||
|
||||
registerClientbound(ClientboundConfigurationPackets1_21_9.REGISTRY_DATA, registryDataRewriter::handle);
|
||||
|
||||
tagRewriter.registerGeneric(ClientboundPackets26_1.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21_9.UPDATE_TAGS);
|
||||
|
||||
// If needed for item or component changes
|
||||
componentRewriter.registerOpenScreen1_14(ClientboundPackets26_1.OPEN_SCREEN);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_ACTION_BAR_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_TITLE_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SET_SUBTITLE_TEXT);
|
||||
componentRewriter.registerBossEvent(ClientboundPackets26_1.BOSS_EVENT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets26_1.DISCONNECT);
|
||||
componentRewriter.registerComponentPacket(ClientboundConfigurationPackets1_21_9.DISCONNECT);
|
||||
componentRewriter.registerTabList(ClientboundPackets26_1.TAB_LIST);
|
||||
componentRewriter.registerSetPlayerTeam1_21_5(ClientboundPackets26_1.SET_PLAYER_TEAM);
|
||||
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets26_1.PLAYER_COMBAT_KILL);
|
||||
componentRewriter.registerPlayerInfoUpdate1_21_4(ClientboundPackets26_1.PLAYER_INFO_UPDATE);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets26_1.SYSTEM_CHAT);
|
||||
componentRewriter.registerDisguisedChat(ClientboundPackets26_1.DISGUISED_CHAT);
|
||||
componentRewriter.registerPlayerChat1_21_5(ClientboundPackets26_1.PLAYER_CHAT);
|
||||
componentRewriter.registerSetObjective(ClientboundPackets26_1.SET_OBJECTIVE);
|
||||
componentRewriter.registerSetScore1_20_3(ClientboundPackets26_1.SET_SCORE);
|
||||
componentRewriter.registerPing();
|
||||
|
||||
// If needed for any particle, item, or block changes. Extend ParticleRewriter for particle serializer changes
|
||||
particleRewriter.registerLevelParticles1_21_4(ClientboundPackets26_1.LEVEL_PARTICLES);
|
||||
particleRewriter.registerExplode1_21_9(ClientboundPackets26_1.EXPLODE); // Rewrites the included sound and particles
|
||||
|
||||
final SoundRewriter<ClientboundPacket26_1> soundRewriter = new SoundRewriter<>(this);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets26_1.SOUND);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets26_1.SOUND_ENTITY);
|
||||
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets26_1.AWARD_STATS);
|
||||
new AttributeRewriter<>(this).register1_21(ClientboundPackets26_1.UPDATE_ATTRIBUTES);
|
||||
// Common registrations (tags, components, particles, sounds, statistics, attributes)
|
||||
// are automatically applied via SharedRegistrations based on the protocol's version range.
|
||||
// Only protocol-specific registrations need to be added here.
|
||||
|
||||
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
|
||||
/*new CommandRewriter1_19_4<>(this) {
|
||||
@@ -125,26 +92,8 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
|
||||
// Uncomment this if the entity types enum has been newly added specifically for this Protocol
|
||||
// EntityTypes1_21_11.initialize(this);
|
||||
|
||||
// Uncomment if a new particle was added = ids shifted; requires a new Types_ class copied from the last
|
||||
/*mappedTypes().particle.filler(this)
|
||||
.reader("block", ParticleType.Readers.BLOCK)
|
||||
.reader("block_marker", ParticleType.Readers.BLOCK)
|
||||
.reader("dust_pillar", ParticleType.Readers.BLOCK)
|
||||
.reader("falling_dust", ParticleType.Readers.BLOCK)
|
||||
.reader("block_crumble", ParticleType.Readers.BLOCK)
|
||||
.reader("dust", ParticleType.Readers.DUST1_21_2)
|
||||
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION1_21_2)
|
||||
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
|
||||
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
|
||||
.reader("shriek", ParticleType.Readers.SHRIEK)
|
||||
.reader("entity_effect", ParticleType.Readers.COLOR)
|
||||
.reader("tinted_leaves", ParticleType.Readers.COLOR)
|
||||
.reader("trail", ParticleType.Readers.TRAIL1_21_4)
|
||||
.reader("dragon_breath", ParticleType.Readers.POWER)
|
||||
.reader("effect", ParticleType.Readers.SPELL)
|
||||
.reader("instant_effect", ParticleType.Readers.SPELL)
|
||||
.reader("flash", ParticleType.Readers.COLOR)
|
||||
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemTemplateType()));*/
|
||||
// Uncomment if versioned types changed
|
||||
// ParticleType.Fillers.fill1_21_9(this);
|
||||
|
||||
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
|
||||
}
|
||||
@@ -152,8 +101,8 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
|
||||
@Override
|
||||
public void init(final UserConnection connection) {
|
||||
// Register the entity tracker - used for entity id/entity data rewriting AND for tracking world data sent to the client (then used for chunk data rewriting)
|
||||
addEntityTracker(connection, new EntityTrackerBase(connection, EntityTypes1_21_11.PLAYER));
|
||||
addItemHasher(connection, new ItemHasherBase(this, connection));
|
||||
addEntityTracker(connection);
|
||||
addItemHasher(connection);
|
||||
}
|
||||
|
||||
// Overriding these methods is important as they are relied on various rewriter classes
|
||||
@@ -173,6 +122,11 @@ final class Protocol98_1To99_1 extends AbstractProtocol<ClientboundPacket26_1, C
|
||||
return itemRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockRewriter<ClientboundPacket26_1> getBlockRewriter() {
|
||||
return blockRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryDataRewriter getRegistryDataRewriter() {
|
||||
return registryDataRewriter;
|
||||
|
||||
+9
-2
@@ -37,7 +37,6 @@ import com.viaversion.viaversion.protocols.v1_10to1_11.rewriter.ItemPacketRewrit
|
||||
import com.viaversion.viaversion.protocols.v1_10to1_11.storage.EntityTracker1_11;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ServerboundPackets1_9_3;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
|
||||
public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3, ClientboundPackets1_9_3, ServerboundPackets1_9_3, ServerboundPackets1_9_3> {
|
||||
|
||||
@@ -59,7 +58,15 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
|
||||
protected void registerPackets() {
|
||||
super.registerPackets();
|
||||
|
||||
new SoundRewriter<>(this, this::getNewSoundId).registerSound(ClientboundPackets1_9_3.SOUND);
|
||||
registerClientbound(ClientboundPackets1_9_3.SOUND, wrapper -> {
|
||||
int soundId = wrapper.read(Types.VAR_INT);
|
||||
int mappedId = getNewSoundId(soundId);
|
||||
if (mappedId == -1) {
|
||||
wrapper.cancel();
|
||||
} else {
|
||||
wrapper.write(Types.VAR_INT, mappedId);
|
||||
}
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_9_3.SET_TITLES, new PacketHandlers() {
|
||||
@Override
|
||||
|
||||
Loaded 100 of 232 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user