mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2026-11-04 17:00:06 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f880adced2 | ||
|
|
fc07601f24 | ||
|
|
ecb241c187 | ||
|
|
46040b1f5d | ||
|
|
54daa11ce4 | ||
|
|
c556420870 | ||
|
|
84d928ebe7 | ||
|
|
fa6eab5cc3 | ||
|
|
94b26a903c | ||
|
|
c242456c30 | ||
|
|
8391e9d924 | ||
|
|
f5aac9b1ab | ||
|
|
a6850392e1 | ||
|
|
2b37178482 | ||
|
|
82199d9f39 | ||
|
|
c2d2c6d067 | ||
|
|
4066a7b5b6 | ||
|
|
4a7624fef4 | ||
|
|
e38b3f3824 | ||
|
|
4573035aab | ||
|
|
393a5ee973 | ||
|
|
080dc18165 | ||
|
|
6fd421d36e | ||
|
|
84bd1d0782 | ||
|
|
cff2303c62 | ||
|
|
f5733c2cb8 | ||
|
|
21fec0e263 | ||
|
|
093acc519e | ||
|
|
886be3161e | ||
|
|
dc7b708556 | ||
|
|
e82f28c1ac | ||
|
|
7c7239a70d | ||
|
|
3e3dad9e33 | ||
|
|
4871977681 | ||
|
|
0a56e57aec | ||
|
|
a6ff477b8a | ||
|
|
ddad0384f3 | ||
|
|
aabe47f8bc | ||
|
|
354a5f1b75 | ||
|
|
f58afd434d | ||
|
|
57d5652cd5 | ||
|
|
25b521dfcf | ||
|
|
ce655d0679 | ||
|
|
e4e8297a82 | ||
|
|
8357fd01aa | ||
|
|
12b420d3e7 | ||
|
|
db20bc0ae4 | ||
|
|
2a2afa3821 | ||
|
|
f0b2d9aafe | ||
|
|
cd427a2a39 | ||
|
|
75537d3f85 | ||
|
|
a88e2f3fb5 | ||
|
|
8a41e7add6 | ||
|
|
9c35228287 | ||
|
|
f9ec6b9d03 | ||
|
|
22d396d909 | ||
|
|
39b28e21ca | ||
|
|
0488cb7fbe | ||
|
|
ec4aa0637e | ||
|
|
ffc5584b1c | ||
|
|
45c6cfedb0 | ||
|
|
c150e50636 | ||
|
|
16e32a62e5 | ||
|
|
1d18f2e45e | ||
|
|
e46b38e58a | ||
|
|
033741d292 | ||
|
|
7a3ef1e0b7 | ||
|
|
5be41ed3e9 | ||
|
|
83e44641d0 | ||
|
|
50084c112d | ||
|
|
81682f4921 | ||
|
|
1c339e8b54 | ||
|
|
1a9cda0579 | ||
|
|
6ad9a71907 | ||
|
|
9f24576ba7 | ||
|
|
8661bbc1fc | ||
|
|
0b5fa37f96 | ||
|
|
dab32bafa1 | ||
|
|
9e5c541f79 | ||
|
|
9674c617ca | ||
|
|
9df1704357 | ||
|
|
c0821de2e2 | ||
|
|
c358c39027 | ||
|
|
451b3a2637 | ||
|
|
619eecacf8 | ||
|
|
6bae039d52 | ||
|
|
b321029886 | ||
|
|
5287d4fb4f | ||
|
|
a0a2794291 | ||
|
|
9e354e956e | ||
|
|
27033e9096 | ||
|
|
e436bbe375 | ||
|
|
050a1dbacb | ||
|
|
ae1838d78a | ||
|
|
7235485802 | ||
|
|
fcb472347e | ||
|
|
e0ce8cc715 | ||
|
|
ebc0e61be8 | ||
|
|
95581a6fa5 | ||
|
|
d0b49009e5 | ||
|
|
369b076cad | ||
|
|
6555bcda74 | ||
|
|
e537dbb024 | ||
|
|
f92dbb655d | ||
|
|
0b2dac9056 | ||
|
|
7cd5514b90 | ||
|
|
5017d4bbb3 | ||
|
|
32e51b52aa | ||
|
|
4f66fd793b | ||
|
|
2a71612aea | ||
|
|
a993a08b8d | ||
|
|
a9c947517c | ||
|
|
2841bf3040 | ||
|
|
7edddda36e | ||
|
|
33de12ceb1 | ||
|
|
f8eb57cdbb | ||
|
|
b2d523f5c0 | ||
|
|
b586b0d361 | ||
|
|
c6381e7f4d | ||
|
|
10ee7e1930 | ||
|
|
78abf8be00 | ||
|
|
1dde24bb68 | ||
|
|
bc57512ca2 | ||
|
|
6ad3beca76 | ||
|
|
9d75125e41 | ||
|
|
8ce4112e86 | ||
|
|
7d542d5667 | ||
|
|
7d6599b90e | ||
|
|
1b03e24160 | ||
|
|
fcd91bb855 | ||
|
|
bda4ea9fd0 | ||
|
|
cbd26ce9d9 | ||
|
|
8d53f4aa5a | ||
|
|
1438f1f68d | ||
|
|
61fcf6f895 | ||
|
|
736834441d |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -0,0 +1,14 @@
|
||||
name: Update Gradle Wrapper
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 0 * * 0"
|
||||
|
||||
jobs:
|
||||
update-gradle-wrapper:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Update Gradle Wrapper
|
||||
uses: gradle-update/update-gradle-wrapper-action@v2
|
||||
@@ -9,9 +9,9 @@ it works on any platform you can think of.**
|
||||
|
||||
The base ViaVersion jar runs on Paper and Velocity. We also have projects integrating ViaVersion to run
|
||||
on Fabric, Forge, Bungee, Sponge, or as a standalone proxy to join from basically any client version on
|
||||
any server version from the past decade. **See [HERE](https://github.com/ViaVersion) for an overview of the different Via\* projects.**
|
||||
any server version from the past decade. **See [HERE](https://viaversion.com) for an overview of the different Via\* projects.**
|
||||
|
||||
Note that ViaVersion will be able to **run best on either Paper servers or Fabric clients** due to having
|
||||
Note that ViaVersion will be able to **run best on either Paper servers or through [ViaFabricPlus](https://github.com/ViaVersion/ViaFabricPlus?tab=readme-ov-file#viafabricplus)** due to having
|
||||
direct access to client/server state and more extensive API.
|
||||
|
||||
Supported Versions:
|
||||
@@ -83,7 +83,7 @@ You need JDK 17 or newer to build ViaVersion.
|
||||
|
||||
Mapping Files
|
||||
--------------
|
||||
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings).
|
||||
Mapping files are generated and managed in our [Mappings repository](https://github.com/ViaVersion/Mappings). The generated mapping output is stored [here](./common/src/main/resources/assets/viaversion).
|
||||
|
||||
|
||||
Resources
|
||||
@@ -96,7 +96,7 @@ Resources
|
||||
|
||||
License
|
||||
--------
|
||||
The entirety of the [API directory](api) (including the legacy API directory) is licensed under the MIT License;
|
||||
The entirety of the [API directory](api) is licensed under the MIT License;
|
||||
see [licenses/MIT.md](licenses/MIT.md) for
|
||||
details.
|
||||
|
||||
|
||||
@@ -19,7 +19,9 @@ dependencies {
|
||||
api(libs.vianbt) {
|
||||
exclude("it.unimi.dsi", "fastutil")
|
||||
}
|
||||
api(libs.gson)
|
||||
api(libs.gson) {
|
||||
exclude("com.google.errorprone", "error_prone_annotations")
|
||||
}
|
||||
implementation(rootProject.libs.text) {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("com.viaversion", "nbt")
|
||||
|
||||
@@ -464,4 +464,18 @@ public interface ViaVersionConfig extends Config {
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean cancelBlockSounds();
|
||||
|
||||
/**
|
||||
* Hides scoreboard numbers for 1.20.3+ clients on older server versions.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean hideScoreboardNumbers();
|
||||
|
||||
/**
|
||||
* Fixes 1.21+ clients on 1.20.5 servers placing water/lava buckets at the wrong location when moving fast.
|
||||
*
|
||||
* @return true if enabled
|
||||
*/
|
||||
boolean fix1_21PlacementRotation();
|
||||
}
|
||||
@@ -29,6 +29,11 @@ public abstract class StoredObject implements StorableObject {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public UserConnection user() {
|
||||
return this.user;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public UserConnection getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ package com.viaversion.viaversion.api.connection;
|
||||
|
||||
import com.viaversion.viaversion.api.configuration.ViaVersionConfig;
|
||||
import com.viaversion.viaversion.api.data.entity.EntityTracker;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketTracker;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
@@ -99,14 +100,33 @@ public interface UserConnection {
|
||||
void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker);
|
||||
|
||||
/**
|
||||
* Clear stored objects and entity trackers.
|
||||
* Returns the client world by the given protocol class if present.
|
||||
*
|
||||
* @param protocolClass protocol class
|
||||
* @param <T> client world type
|
||||
* @return client world if present
|
||||
*/
|
||||
@Nullable
|
||||
<T extends ClientWorld> T getClientWorld(Class<? extends Protocol> protocolClass);
|
||||
|
||||
/**
|
||||
* Adds a client world to the user connection.
|
||||
* Does not override existing client worlds.
|
||||
*
|
||||
* @param protocolClass protocol class
|
||||
* @param clientWorld client world
|
||||
*/
|
||||
void addClientWorld(Class<? extends Protocol> protocolClass, ClientWorld clientWorld);
|
||||
|
||||
/**
|
||||
* Clear stored objects, entity trackers and client worlds.
|
||||
*/
|
||||
default void clearStoredObjects() {
|
||||
clearStoredObjects(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear stored objects and entity trackers.
|
||||
* Clear stored objects, entity trackers and client worlds.
|
||||
* If cleared for a proxy server switch, some stored objects and tracker data will be retained.
|
||||
*
|
||||
* @param isServerSwitch whether the clear is due to a server switch
|
||||
|
||||
@@ -53,6 +53,14 @@ public interface FullMappings extends BiMappings {
|
||||
*/
|
||||
@Nullable String identifier(int id);
|
||||
|
||||
/**
|
||||
* Returns the unmapped string identifier for the given mapped identifier.
|
||||
*
|
||||
* @param mappedIdentifier mapped identifier
|
||||
* @return unmapped string identifier, or null if not found
|
||||
*/
|
||||
@Nullable String identifier(String mappedIdentifier);
|
||||
|
||||
/**
|
||||
* Returns the mapped string identifier for the given mapped id.
|
||||
*
|
||||
|
||||
@@ -83,6 +83,17 @@ public class FullMappingsBase implements FullMappings {
|
||||
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 String mappedIdentifier(final int mappedId) {
|
||||
if (mappedId < 0 || mappedId >= mappedIdToString.length) {
|
||||
|
||||
@@ -83,6 +83,10 @@ public interface MappingData {
|
||||
|
||||
int getNewAttributeId(int id);
|
||||
|
||||
int getNewSoundId(int id);
|
||||
|
||||
int getOldSoundId(int i);
|
||||
|
||||
/**
|
||||
* Returns a list of tags to send if present.
|
||||
*
|
||||
@@ -122,10 +126,10 @@ public interface MappingData {
|
||||
|
||||
@Nullable Mappings getEnchantmentMappings();
|
||||
|
||||
@Nullable Mappings getAttributeMappings();
|
||||
|
||||
@Nullable Mappings getPaintingMappings();
|
||||
|
||||
@Nullable FullMappings getAttributeMappings();
|
||||
|
||||
@Nullable FullMappings getEntityMappings();
|
||||
|
||||
@Nullable FullMappings getArgumentTypeMappings();
|
||||
|
||||
@@ -43,10 +43,10 @@ public class MappingDataBase implements MappingData {
|
||||
protected FullMappings entityMappings;
|
||||
protected FullMappings recipeSerializerMappings;
|
||||
protected FullMappings itemDataSerializerMappings;
|
||||
protected FullMappings attributeMappings;
|
||||
protected ParticleMappings particleMappings;
|
||||
protected BiMappings itemMappings;
|
||||
protected BiMappings blockMappings;
|
||||
protected BiMappings attributeMappings;
|
||||
protected Mappings blockStateMappings;
|
||||
protected Mappings blockEntityMappings;
|
||||
protected Mappings soundMappings;
|
||||
@@ -76,8 +76,6 @@ public class MappingDataBase implements MappingData {
|
||||
menuMappings = loadMappings(data, "menus");
|
||||
enchantmentMappings = loadMappings(data, "enchantments");
|
||||
paintingMappings = loadMappings(data, "paintings");
|
||||
attributeMappings = loadBiMappings(data, "attributes");
|
||||
|
||||
|
||||
final CompoundTag unmappedIdentifierData = readUnmappedIdentifiersFile("identifiers-" + unmappedVersion + ".nbt");
|
||||
final CompoundTag mappedIdentifierData = readMappedIdentifiersFile("identifiers-" + mappedVersion + ".nbt");
|
||||
@@ -87,6 +85,7 @@ public class MappingDataBase implements MappingData {
|
||||
argumentTypeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "argumenttypes");
|
||||
recipeSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "recipe_serializers");
|
||||
itemDataSerializerMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "data_component_type");
|
||||
attributeMappings = loadFullMappings(data, unmappedIdentifierData, mappedIdentifierData, "attributes");
|
||||
|
||||
final List<String> unmappedParticles = identifiersFromGlobalIds(unmappedIdentifierData, "particles");
|
||||
final List<String> mappedParticles = identifiersFromGlobalIds(mappedIdentifierData, "particles");
|
||||
@@ -203,6 +202,16 @@ public class MappingDataBase implements MappingData {
|
||||
return checkValidity(id, attributeMappings.getNewId(id), "attributes");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNewSoundId(final int id) {
|
||||
return checkValidity(id, soundMappings.getNewId(id), "sound");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOldSoundId(final int i) {
|
||||
return soundMappings.getNewIdOrDefault(i, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable List<TagData> getTags(final RegistryType type) {
|
||||
return tags != null ? tags.get(type) : null;
|
||||
@@ -262,7 +271,7 @@ public class MappingDataBase implements MappingData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Mappings getAttributeMappings() {
|
||||
public @Nullable FullMappings getAttributeMappings() {
|
||||
return attributeMappings;
|
||||
}
|
||||
|
||||
@@ -315,4 +324,4 @@ public class MappingDataBase implements MappingData {
|
||||
|
||||
protected void loadExtras(final CompoundTag data) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.viaversion.nbt.io.NBTIO;
|
||||
import com.viaversion.nbt.io.TagReader;
|
||||
import com.viaversion.nbt.tag.ByteTag;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.IntArrayTag;
|
||||
import com.viaversion.nbt.tag.IntTag;
|
||||
@@ -211,68 +210,64 @@ public class MappingDataLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
final ByteTag serializationStragetyTag = tag.getUnchecked("id");
|
||||
final IntTag mappedSizeTag = tag.getUnchecked("mappedSize");
|
||||
final byte strategy = serializationStragetyTag.asByte();
|
||||
final int mappedSize = tag.getIntTag("mappedSize").asInt();
|
||||
final byte strategy = tag.getByteTag("id").asByte();
|
||||
final V mappings;
|
||||
if (strategy == DIRECT_ID) {
|
||||
final IntArrayTag valuesTag = tag.getIntArrayTag("val");
|
||||
return IntArrayMappings.of(valuesTag.getValue(), mappedSizeTag.asInt());
|
||||
return IntArrayMappings.of(valuesTag.getValue(), mappedSize);
|
||||
} else if (strategy == SHIFTS_ID) {
|
||||
final IntArrayTag shiftsAtTag = tag.getIntArrayTag("at");
|
||||
final IntArrayTag shiftsTag = tag.getIntArrayTag("to");
|
||||
final IntTag sizeTag = tag.getUnchecked("size");
|
||||
final int[] shiftsAt = shiftsAtTag.getValue();
|
||||
final int[] shiftsTo = shiftsTag.getValue();
|
||||
final int size = sizeTag.asInt();
|
||||
final int[] shiftsAt = tag.getIntArrayTag("at").getValue();
|
||||
final int[] shiftsTo = tag.getIntArrayTag("to").getValue();
|
||||
final int size = tag.getIntTag("size").asInt();
|
||||
mappings = holderSupplier.get(size);
|
||||
|
||||
// Handle values until first shift
|
||||
if (shiftsAt[0] != 0) {
|
||||
// Add identity values before the first shift
|
||||
final int to = shiftsAt[0];
|
||||
for (int id = 0; id < to; id++) {
|
||||
addConsumer.addTo(mappings, id, id);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle shifts
|
||||
// Read shifts
|
||||
for (int i = 0; i < shiftsAt.length; i++) {
|
||||
final boolean isLast = i == shiftsAt.length - 1;
|
||||
final int from = shiftsAt[i];
|
||||
final int to = i == shiftsAt.length - 1 ? size : shiftsAt[i + 1];
|
||||
final int to = isLast ? size : shiftsAt[i + 1];
|
||||
int mappedId = shiftsTo[i];
|
||||
for (int id = from; id < to; id++) {
|
||||
addConsumer.addTo(mappings, id, mappedId++);
|
||||
}
|
||||
}
|
||||
} else if (strategy == CHANGES_ID) {
|
||||
final IntArrayTag changesAtTag = tag.getIntArrayTag("at");
|
||||
final IntArrayTag valuesTag = tag.getIntArrayTag("val");
|
||||
final IntTag sizeTag = tag.getUnchecked("size");
|
||||
final int[] changesAt = tag.getIntArrayTag("at").getValue();
|
||||
final int[] values = tag.getIntArrayTag("val").getValue();
|
||||
final int size = tag.getIntTag("size").asInt();
|
||||
final boolean fillBetween = tag.get("nofill") == null;
|
||||
final int[] changesAt = changesAtTag.getValue();
|
||||
final int[] values = valuesTag.getValue();
|
||||
mappings = holderSupplier.get(sizeTag.asInt());
|
||||
mappings = holderSupplier.get(size);
|
||||
|
||||
int nextUnhandledId = 0;
|
||||
for (int i = 0; i < changesAt.length; i++) {
|
||||
final int id = changesAt[i];
|
||||
final int changedId = changesAt[i];
|
||||
if (fillBetween) {
|
||||
// Fill from after the last change to before this change with unchanged ids
|
||||
final int previousId = i != 0 ? changesAt[i - 1] + 1 : 0;
|
||||
for (int identity = previousId; identity < id; identity++) {
|
||||
addConsumer.addTo(mappings, identity, identity);
|
||||
for (int id = nextUnhandledId; id < changedId; id++) {
|
||||
addConsumer.addTo(mappings, id, id);
|
||||
}
|
||||
nextUnhandledId = changedId + 1;
|
||||
}
|
||||
|
||||
// Assign the changed value
|
||||
addConsumer.addTo(mappings, id, values[i]);
|
||||
addConsumer.addTo(mappings, changedId, values[i]);
|
||||
}
|
||||
} else if (strategy == IDENTITY_ID) {
|
||||
final IntTag sizeTag = tag.getUnchecked("size");
|
||||
return new IdentityMappings(sizeTag.asInt(), mappedSizeTag.asInt());
|
||||
final IntTag sizeTag = tag.getIntTag("size");
|
||||
return new IdentityMappings(sizeTag.asInt(), mappedSize);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unknown serialization strategy: " + strategy);
|
||||
}
|
||||
return mappingsSupplier.create(mappings, mappedSizeTag.asInt());
|
||||
return mappingsSupplier.create(mappings, mappedSize);
|
||||
}
|
||||
|
||||
public @Nullable List<String> identifiersFromGlobalIds(final CompoundTag mappingsTag, final String key) {
|
||||
@@ -295,7 +290,7 @@ public class MappingDataLoader {
|
||||
* @return map with indexes hashed by their id value
|
||||
*/
|
||||
public Object2IntMap<String> indexedObjectToMap(final JsonObject object) {
|
||||
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(object.size(), .99F);
|
||||
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(object.size());
|
||||
map.defaultReturnValue(-1);
|
||||
for (final Map.Entry<String, JsonElement> entry : object.entrySet()) {
|
||||
map.put(entry.getValue().getAsString(), Integer.parseInt(entry.getKey()));
|
||||
@@ -310,7 +305,7 @@ public class MappingDataLoader {
|
||||
* @return map with indexes hashed by their id value
|
||||
*/
|
||||
public Object2IntMap<String> arrayToMap(final JsonArray array) {
|
||||
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(array.size(), .99F);
|
||||
final Object2IntMap<String> map = new Object2IntOpenHashMap<>(array.size());
|
||||
map.defaultReturnValue(-1);
|
||||
for (int i = 0; i < array.size(); i++) {
|
||||
map.put(array.get(i).getAsString(), i);
|
||||
|
||||
@@ -78,7 +78,7 @@ public interface EntityTracker {
|
||||
void removeEntity(int id);
|
||||
|
||||
/**
|
||||
* Clears stored entity types and data.
|
||||
* Clears stored entity types and data, only leaving behind the client entity.
|
||||
*/
|
||||
void clearEntities();
|
||||
|
||||
@@ -102,11 +102,19 @@ public interface EntityTracker {
|
||||
@Nullable StoredEntityData entityDataIfPresent(int id);
|
||||
|
||||
/**
|
||||
* Returns the client entity id or -1 if unset.
|
||||
* Returns whether the client entity id has been set.
|
||||
*
|
||||
* @return client entity id or -1 if unset
|
||||
* @return whether the client entity id has been set
|
||||
*/
|
||||
int clientEntityId();
|
||||
boolean hasClientEntityId();
|
||||
|
||||
/**
|
||||
* Returns the client entity id. Should be wrapped around {@link #hasClientEntityId()}.
|
||||
*
|
||||
* @return client entity id
|
||||
* @throws IllegalStateException if the client entity id has not been set
|
||||
*/
|
||||
int clientEntityId() throws IllegalStateException;
|
||||
|
||||
/**
|
||||
* Sets the client entity id.
|
||||
@@ -169,12 +177,4 @@ public interface EntityTracker {
|
||||
@Nullable DimensionData dimensionData(int dimensionId);
|
||||
|
||||
void setDimensions(Map<String, DimensionData> dimensions);
|
||||
|
||||
/**
|
||||
* Adds the client player entity to the tracker.
|
||||
* If the client entity has not been set yet, this will return false.
|
||||
*
|
||||
* @return whether the client has been tracked
|
||||
*/
|
||||
boolean trackClientEntity();
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public interface DebugHandler {
|
||||
|
||||
/**
|
||||
* Returns whether packets should be logged after being transformed.
|
||||
* Set to true by default.
|
||||
* Set to false by default.
|
||||
*
|
||||
* @return whether packets should be logged after being transformed
|
||||
*/
|
||||
|
||||
@@ -23,13 +23,12 @@
|
||||
package com.viaversion.viaversion.api.minecraft;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Stored up until 1.14 to be used in chunk sending.
|
||||
*/
|
||||
public class ClientWorld implements StorableObject {
|
||||
private Environment environment;
|
||||
private Environment environment = Environment.NORMAL;
|
||||
|
||||
public ClientWorld() {
|
||||
}
|
||||
@@ -38,11 +37,20 @@ public class ClientWorld implements StorableObject {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
public @Nullable Environment getEnvironment() {
|
||||
public Environment getEnvironment() {
|
||||
return environment;
|
||||
}
|
||||
|
||||
public void setEnvironment(final int environmentId) {
|
||||
/**
|
||||
* Sets the environment of the world and returns whether the environment was changed.
|
||||
*
|
||||
* @param environmentId the id of the environment to set
|
||||
* @return whether the environment was changed
|
||||
*/
|
||||
public boolean setEnvironment(final int environmentId) {
|
||||
final int previousEnvironmentId = environment.id();
|
||||
this.environment = Environment.getEnvironmentById(environmentId);
|
||||
|
||||
return previousEnvironmentId != environmentId;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
public interface Holder<T> {
|
||||
|
||||
/**
|
||||
@@ -33,7 +35,7 @@ public interface Holder<T> {
|
||||
* @throws IllegalArgumentException if the id is negative
|
||||
*/
|
||||
static <T> Holder<T> of(final int id) {
|
||||
return new HolderImpl<>(id);
|
||||
return new IdHolder<>(id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +46,7 @@ public interface Holder<T> {
|
||||
* @return a new direct holder
|
||||
*/
|
||||
static <T> Holder<T> of(final T value) {
|
||||
return new HolderImpl<>(value);
|
||||
return new ValueHolder<>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,4 +81,12 @@ public interface Holder<T> {
|
||||
* @see #hasId()
|
||||
*/
|
||||
int id();
|
||||
|
||||
/**
|
||||
* Returns a new holder with the id rewritten using the given function, or self if this is a direct holder or the id did not change.
|
||||
*
|
||||
* @param rewriteFunction the function to rewrite the id
|
||||
* @return a new holder with the id rewritten, or self
|
||||
*/
|
||||
Holder<T> updateId(final Int2IntFunction rewriteFunction);
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public interface HolderSet {
|
||||
* @return a new holder set
|
||||
*/
|
||||
static HolderSet of(final String tagKey) {
|
||||
return new HolderSetImpl(tagKey);
|
||||
return new HolderSetImpl.Tag(tagKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,7 +46,7 @@ public interface HolderSet {
|
||||
* @return a new holder set
|
||||
*/
|
||||
static HolderSet of(final int[] ids) {
|
||||
return new HolderSetImpl(ids);
|
||||
return new HolderSetImpl.Ids(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,50 +22,63 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft;
|
||||
|
||||
import com.viaversion.viaversion.util.EitherImpl;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
import java.util.Arrays;
|
||||
|
||||
final class HolderSetImpl extends EitherImpl<String, int[]> implements HolderSet {
|
||||
final class HolderSetImpl {
|
||||
|
||||
HolderSetImpl(final String tagKey) {
|
||||
super(tagKey, null);
|
||||
}
|
||||
record Tag(String tagKey) implements HolderSet {
|
||||
@Override
|
||||
public boolean hasTagKey() {
|
||||
return true;
|
||||
}
|
||||
|
||||
HolderSetImpl(final int[] ids) {
|
||||
super(null, ids);
|
||||
}
|
||||
@Override
|
||||
public int[] ids() {
|
||||
throw new IllegalArgumentException("This holder set has a tag key");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tagKey() {
|
||||
return left();
|
||||
}
|
||||
@Override
|
||||
public boolean hasIds() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTagKey() {
|
||||
return isLeft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] ids() {
|
||||
return right();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIds() {
|
||||
return isRight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
||||
if (hasTagKey()) {
|
||||
@Override
|
||||
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
final int[] ids = ids();
|
||||
final int[] mappedIds = new int[ids.length];
|
||||
for (int i = 0; i < mappedIds.length; i++) {
|
||||
mappedIds[i] = idRewriter.apply(ids[i]);
|
||||
record Ids(int[] ids) implements HolderSet {
|
||||
@Override
|
||||
public boolean hasTagKey() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tagKey() {
|
||||
throw new IllegalArgumentException("This holder set has direct ids");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HolderSet rewrite(final Int2IntFunction idRewriter) {
|
||||
final int[] mappedIds = new int[ids.length];
|
||||
for (int i = 0; i < mappedIds.length; i++) {
|
||||
mappedIds[i] = idRewriter.applyAsInt(ids[i]);
|
||||
}
|
||||
return new Ids(mappedIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Ids{" +
|
||||
"ids=" + Arrays.toString(ids) +
|
||||
'}';
|
||||
}
|
||||
return new HolderSetImpl(mappedIds);
|
||||
}
|
||||
}
|
||||
+15
-26
@@ -23,49 +23,38 @@
|
||||
package com.viaversion.viaversion.api.minecraft;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
final class HolderImpl<T> implements Holder<T> {
|
||||
record IdHolder<T>(int id) implements Holder<T> {
|
||||
|
||||
private final T value;
|
||||
private final int id;
|
||||
|
||||
HolderImpl(final int id) {
|
||||
IdHolder {
|
||||
Preconditions.checkArgument(id >= 0, "id cannot be negative");
|
||||
this.value = null;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
HolderImpl(final T value) {
|
||||
this.value = value;
|
||||
this.id = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return id == -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasId() {
|
||||
return id != -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T value() {
|
||||
Preconditions.checkArgument(isDirect(), "Holder is not direct");
|
||||
return value;
|
||||
throw new IllegalArgumentException("Holder is not direct");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HolderImpl{" +
|
||||
"value=" + value +
|
||||
", id=" + id +
|
||||
'}';
|
||||
public Holder<T> updateId(final Int2IntFunction rewriteFunction) {
|
||||
final int rewrittenId = rewriteFunction.applyAsInt(id);
|
||||
if (rewrittenId == id) {
|
||||
return this;
|
||||
}
|
||||
if (rewrittenId == -1) {
|
||||
throw new IllegalArgumentException("Received invalid id in updateId");
|
||||
}
|
||||
return Holder.of(rewrittenId);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.util.IdHolder;
|
||||
@@ -72,6 +73,14 @@ public final class Particle implements IdHolder {
|
||||
arguments.set(index, new ParticleData<>(type, value));
|
||||
}
|
||||
|
||||
public Particle copy() {
|
||||
final Particle particle = new Particle(id);
|
||||
for (ParticleData<?> argument : arguments) {
|
||||
particle.arguments.add(argument.copy());
|
||||
}
|
||||
return particle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Particle{" +
|
||||
@@ -109,6 +118,14 @@ public final class Particle implements IdHolder {
|
||||
wrapper.write(type, value);
|
||||
}
|
||||
|
||||
public ParticleData<T> copy() {
|
||||
if (value instanceof Item item) {
|
||||
return new ParticleData<>(type, (T) item.copy());
|
||||
} else {
|
||||
return new ParticleData<>(type, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ParticleData{" +
|
||||
|
||||
@@ -36,4 +36,8 @@ public record RegistryEntry(String key, @Nullable Tag tag) {
|
||||
public RegistryEntry withKey(final String key) {
|
||||
return new RegistryEntry(key, tag != null ? tag.copy() : null);
|
||||
}
|
||||
|
||||
public RegistryEntry copy() {
|
||||
return new RegistryEntry(key, tag != null ? tag.copy() : null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
record ValueHolder<T>(T value) implements Holder<T> {
|
||||
|
||||
@Override
|
||||
public boolean isDirect() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasId() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Holder<T> updateId(final Int2IntFunction rewriteFunction) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -37,14 +37,14 @@ public class ChunkSectionImpl implements ChunkSection {
|
||||
public ChunkSectionImpl(final boolean holdsLight) {
|
||||
addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE));
|
||||
if (holdsLight) {
|
||||
this.light = new ChunkSectionLightImpl();
|
||||
this.light = ChunkSectionLightImpl.createWithBlockLight();
|
||||
}
|
||||
}
|
||||
|
||||
public ChunkSectionImpl(final boolean holdsLight, final int expectedPaletteLength) {
|
||||
addPalette(PaletteType.BLOCKS, new DataPaletteImpl(ChunkSection.SIZE, expectedPaletteLength));
|
||||
if (holdsLight) {
|
||||
this.light = new ChunkSectionLightImpl();
|
||||
this.light = ChunkSectionLightImpl.createWithBlockLight();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@ public interface ChunkSectionLight {
|
||||
/**
|
||||
* Returns whether the section has sky light.
|
||||
*
|
||||
* @return true if skylight is present
|
||||
* @return true if sky light is present
|
||||
*/
|
||||
boolean hasSkyLight();
|
||||
|
||||
@@ -43,7 +43,7 @@ public interface ChunkSectionLight {
|
||||
* Returns whether the section has block light.
|
||||
* This returns true unless specifically set to null.
|
||||
*
|
||||
* @return true if skylight is present
|
||||
* @return true if block light is present
|
||||
*/
|
||||
boolean hasBlockLight();
|
||||
|
||||
|
||||
+11
-3
@@ -30,9 +30,17 @@ public class ChunkSectionLightImpl implements ChunkSectionLight {
|
||||
private NibbleArray blockLight;
|
||||
private NibbleArray skyLight;
|
||||
|
||||
public ChunkSectionLightImpl() {
|
||||
// Block light is always written
|
||||
this.blockLight = new NibbleArray(ChunkSection.SIZE);
|
||||
protected ChunkSectionLightImpl() {
|
||||
}
|
||||
|
||||
public static ChunkSectionLight createWithBlockLight() {
|
||||
final ChunkSectionLightImpl light = new ChunkSectionLightImpl();
|
||||
light.blockLight = new NibbleArray(ChunkSection.SIZE);
|
||||
return light;
|
||||
}
|
||||
|
||||
public static ChunkSectionLight createEmpty() {
|
||||
return new ChunkSectionLightImpl();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,16 +52,14 @@ public interface StructuredData<T> extends IdHolder {
|
||||
return new EmptyStructuredData<>(key, id);
|
||||
}
|
||||
|
||||
void setValue(final T value);
|
||||
@Nullable T value();
|
||||
|
||||
void write(final ByteBuf buffer);
|
||||
void setValue(final T value);
|
||||
|
||||
void setId(final int id);
|
||||
|
||||
StructuredDataKey<T> key();
|
||||
|
||||
@Nullable T value();
|
||||
|
||||
/**
|
||||
* Returns whether the structured data is present. Even if true, the value may be null.
|
||||
*
|
||||
@@ -77,4 +75,6 @@ public interface StructuredData<T> extends IdHolder {
|
||||
* @return true if the structured data is empty
|
||||
*/
|
||||
boolean isEmpty();
|
||||
|
||||
void write(final ByteBuf buffer);
|
||||
}
|
||||
+127
-72
@@ -33,6 +33,26 @@ import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Loosely represents Minecraft's data component patch, but may also be used for an item's full data components.
|
||||
* <p>
|
||||
* The most commonly used methods will ignore empty data (aka empty overrides that remove item defaults) since those will rarely be needed.
|
||||
* These are:
|
||||
* <ul>
|
||||
* <li>{@link #get(StructuredDataKey)}</li>
|
||||
* <li>{@link #set(StructuredDataKey, Object)}</li>
|
||||
* <li>{@link #set(StructuredDataKey)}</li>
|
||||
* <li>{@link #getNonEmptyData(StructuredDataKey)}</li>
|
||||
* <li>{@link #hasValue(StructuredDataKey)}</li>
|
||||
* </ul>
|
||||
*
|
||||
* To interact with empty patches specifically, use:
|
||||
* <ul>
|
||||
* <li>{@link #setEmpty(StructuredDataKey)}</li>
|
||||
* <li>{@link #hasEmpty(StructuredDataKey)}</li>
|
||||
* </ul>
|
||||
* Other methods (e.g. {@link #getData(StructuredDataKey)} and {@link #has(StructuredDataKey)}) will handle both empty and non-empty data.
|
||||
*/
|
||||
public final class StructuredDataContainer {
|
||||
|
||||
private final Map<StructuredDataKey<?>, StructuredData<?>> data;
|
||||
@@ -55,66 +75,45 @@ public final class StructuredDataContainer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns structured data by id if present.
|
||||
* Returns the non-empty value by id if present.
|
||||
*
|
||||
* @param key serializer id
|
||||
* @param <T> data type
|
||||
* @return structured data
|
||||
* @see #hasEmpty(StructuredDataKey)
|
||||
*/
|
||||
public @Nullable <T> T get(final StructuredDataKey<T> key) {
|
||||
final StructuredData<?> data = this.data.get(key);
|
||||
if (data == null || data.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
//noinspection unchecked
|
||||
return ((StructuredData<T>) data).value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns structured data by id if present, either empty or non-empty.
|
||||
*
|
||||
* @param key serializer id
|
||||
* @param <T> data type
|
||||
* @return structured data
|
||||
*/
|
||||
public @Nullable <T> StructuredData<T> get(final StructuredDataKey<T> key) {
|
||||
public @Nullable <T> StructuredData<T> getData(final StructuredDataKey<T> key) {
|
||||
//noinspection unchecked
|
||||
return (StructuredData<T>) this.data.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns structured data by id if not empty.
|
||||
* Returns non-empty structured data by id if present.
|
||||
*
|
||||
* @param key serializer id
|
||||
* @param <T> data type
|
||||
* @return structured data if not empty
|
||||
* @return non-empty structured data
|
||||
*/
|
||||
public @Nullable <T> StructuredData<T> getNonEmpty(final StructuredDataKey<T> key) {
|
||||
public @Nullable <T> StructuredData<T> getNonEmptyData(final StructuredDataKey<T> key) {
|
||||
final StructuredData<?> data = this.data.get(key);
|
||||
//noinspection unchecked
|
||||
final StructuredData<T> data = (StructuredData<T>) this.data.get(key);
|
||||
return data != null && data.isPresent() ? data : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns structured data by id if not empty, or creates it.
|
||||
*
|
||||
* @param key serializer id
|
||||
* @param mappingFunction function to create structured data if not present
|
||||
* @param <T> data type
|
||||
* @return structured data if not empty
|
||||
*/
|
||||
public <T> StructuredData<T> computeIfAbsent(final StructuredDataKey<T> key, final Function<StructuredDataKey<T>, T> mappingFunction) {
|
||||
final StructuredData<T> data = this.getNonEmpty(key);
|
||||
if (data != null) {
|
||||
return data;
|
||||
}
|
||||
|
||||
final int id = serializerId(key);
|
||||
final StructuredData<T> empty = StructuredData.of(key, mappingFunction.apply(key), id);
|
||||
this.data.put(key, empty);
|
||||
return empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates and returns the structured data by id if not empty.
|
||||
*
|
||||
* @param key serializer id
|
||||
* @param mappingFunction function to update existing data
|
||||
* @param <T> data type
|
||||
* @return updated structured data if not empty
|
||||
*/
|
||||
public <T> @Nullable StructuredData<T> updateIfPresent(final StructuredDataKey<T> key, final Function<T, T> mappingFunction) {
|
||||
final StructuredData<T> data = this.getNonEmpty(key);
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
data.setValue(mappingFunction.apply(data.value()));
|
||||
return data;
|
||||
return data != null && data.isPresent() ? (StructuredData<T>) data : null;
|
||||
}
|
||||
|
||||
public <T> void set(final StructuredDataKey<T> key, final T value) {
|
||||
@@ -124,49 +123,105 @@ public final class StructuredDataContainer {
|
||||
}
|
||||
}
|
||||
|
||||
public <T> void replaceKey(final StructuredDataKey<T> key, final StructuredDataKey<T> toKey) {
|
||||
replace(key, toKey, Function.identity());
|
||||
}
|
||||
|
||||
public <T, V> void replace(final StructuredDataKey<T> key, final StructuredDataKey<V> toKey, final Function<T, V> valueMapper) {
|
||||
final StructuredData<T> data = remove(key);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.isPresent()) {
|
||||
set(toKey, valueMapper.apply(data.value()));
|
||||
} else {
|
||||
addEmpty(toKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void set(final StructuredDataKey<Unit> key) {
|
||||
this.set(key, Unit.INSTANCE);
|
||||
}
|
||||
|
||||
public void addEmpty(final StructuredDataKey<?> key) {
|
||||
public void setEmpty(final StructuredDataKey<?> key) {
|
||||
// Empty optional to override the Minecraft default
|
||||
this.data.put(key, StructuredData.empty(key, serializerId(key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns structured data by the given key.
|
||||
* Updates the structured data by id if not empty.
|
||||
*
|
||||
* @param key serializer key
|
||||
* @param <T> data type
|
||||
* @return removed structured data
|
||||
* @param key serializer id
|
||||
* @param valueMapper function to update existing data
|
||||
* @param <T> data type
|
||||
*/
|
||||
public @Nullable <T> StructuredData<T> remove(final StructuredDataKey<T> key) {
|
||||
final StructuredData<?> data = this.data.remove(key);
|
||||
//noinspection unchecked
|
||||
return data != null ? (StructuredData<T>) data : null;
|
||||
public <T> void replace(final StructuredDataKey<T> key, final Function<T, @Nullable T> valueMapper) {
|
||||
final StructuredData<T> data = this.getNonEmptyData(key);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final T replacement = valueMapper.apply(data.value());
|
||||
if (replacement != null) {
|
||||
data.setValue(replacement);
|
||||
} else {
|
||||
this.data.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(final StructuredDataKey<?> key) {
|
||||
public <T> void replaceKey(final StructuredDataKey<T> key, final StructuredDataKey<T> toKey) {
|
||||
replace(key, toKey, Function.identity());
|
||||
}
|
||||
|
||||
public <T, V> void replace(final StructuredDataKey<T> key, final StructuredDataKey<V> toKey, final Function<T, @Nullable V> valueMapper) {
|
||||
final StructuredData<?> data = this.data.remove(key);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.isPresent()) {
|
||||
//noinspection unchecked
|
||||
final T value = (T) data.value();
|
||||
final V replacement = valueMapper.apply(value);
|
||||
if (replacement != null) {
|
||||
set(toKey, replacement);
|
||||
}
|
||||
} else {
|
||||
// Also replace the key for empty data
|
||||
setEmpty(toKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes data by the given key.
|
||||
*
|
||||
* @param key data key
|
||||
* @see #replace(StructuredDataKey, Function)
|
||||
* @see #replace(StructuredDataKey, StructuredDataKey, Function)
|
||||
* @see #replaceKey(StructuredDataKey, StructuredDataKey)
|
||||
*/
|
||||
public void remove(final StructuredDataKey<?> key) {
|
||||
this.data.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is data for the given key, either empty or non-empty.
|
||||
*
|
||||
* @param key data key
|
||||
* @return whether there data for the given key
|
||||
* @see #hasEmpty(StructuredDataKey)
|
||||
* @see #hasValue(StructuredDataKey)
|
||||
*/
|
||||
public boolean has(final StructuredDataKey<?> key) {
|
||||
return this.data.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether there is non-empty data for the given key.
|
||||
*
|
||||
* @param key data key
|
||||
* @return whether there is non-empty data for the given key
|
||||
*/
|
||||
public boolean hasValue(final StructuredDataKey<?> key) {
|
||||
final StructuredData<?> data = this.data.get(key);
|
||||
return data != null && data.isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the structured data has an empty patch/override.
|
||||
*
|
||||
* @param key serializer id
|
||||
* @return whether the structured data has an empty patch/override
|
||||
*/
|
||||
public boolean hasEmpty(final StructuredDataKey<?> key) {
|
||||
final StructuredData<?> data = this.data.get(key);
|
||||
return data != null && data.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lookup for serializer ids. Required to call most of the other methods.
|
||||
*
|
||||
|
||||
+32
-6
@@ -26,6 +26,7 @@ import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.minecraft.GameProfile;
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.HolderSet;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.AdventureModePredicate;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.ArmorTrim;
|
||||
@@ -34,13 +35,19 @@ import com.viaversion.viaversion.api.minecraft.item.data.AttributeModifiers1_21;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BannerPatternLayer;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Bee;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BlockStateProperties;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.DamageResistant;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.DeathProtection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.DyedColor;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Equippable;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.FilterableString;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.FireworkExplosion;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Fireworks;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Instrument;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_20_5;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.FoodProperties1_21_2;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_20_5;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Instrument1_21_2;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.JukeboxPlayable;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTracker;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.PotDecorations;
|
||||
@@ -48,11 +55,13 @@ import com.viaversion.viaversion.api.minecraft.item.data.PotionContents;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.SuspiciousStewEffect;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.ToolProperties;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Unbreakable;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.UseCooldown;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21_2;
|
||||
import com.viaversion.viaversion.util.Unit;
|
||||
|
||||
public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
@@ -64,6 +73,7 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<Unbreakable> UNBREAKABLE = new StructuredDataKey<>("unbreakable", Unbreakable.TYPE);
|
||||
public static final StructuredDataKey<Tag> CUSTOM_NAME = new StructuredDataKey<>("custom_name", Types.TAG);
|
||||
public static final StructuredDataKey<Tag> ITEM_NAME = new StructuredDataKey<>("item_name", Types.TAG);
|
||||
public static final StructuredDataKey<String> ITEM_MODEL = new StructuredDataKey<>("item_model", Types.STRING);
|
||||
public static final StructuredDataKey<Tag[]> LORE = new StructuredDataKey<>("lore", Types.TAG_ARRAY);
|
||||
public static final StructuredDataKey<Integer> RARITY = new StructuredDataKey<>("rarity", Types.VAR_INT);
|
||||
public static final StructuredDataKey<Enchantments> ENCHANTMENTS = new StructuredDataKey<>("enchantments", Enchantments.TYPE);
|
||||
@@ -78,10 +88,21 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<Unit> CREATIVE_SLOT_LOCK = new StructuredDataKey<>("creative_slot_lock", Types.EMPTY);
|
||||
public static final StructuredDataKey<Boolean> ENCHANTMENT_GLINT_OVERRIDE = new StructuredDataKey<>("enchantment_glint_override", Types.BOOLEAN);
|
||||
public static final StructuredDataKey<Tag> INTANGIBLE_PROJECTILE = new StructuredDataKey<>("intangible_projectile", Types.TAG); // Doesn't actually hold data
|
||||
public static final StructuredDataKey<FoodProperties> FOOD1_20_5 = new StructuredDataKey<>("food", FoodProperties.TYPE1_20_5);
|
||||
public static final StructuredDataKey<FoodProperties> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties.TYPE1_21);
|
||||
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_20_5 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_20_5);
|
||||
public static final StructuredDataKey<FoodProperties1_20_5> FOOD1_21 = new StructuredDataKey<>("food", FoodProperties1_20_5.TYPE1_21);
|
||||
public static final StructuredDataKey<FoodProperties1_21_2> FOOD1_21_2 = new StructuredDataKey<>("food", FoodProperties1_21_2.TYPE);
|
||||
public static final StructuredDataKey<Consumable1_21_2> CONSUMABLE1_21_2 = new StructuredDataKey<>("consumable", Consumable1_21_2.TYPE);
|
||||
public static final StructuredDataKey<Item> USE_REMAINDER = new StructuredDataKey<>("use_remainder", Types1_21_2.ITEM);
|
||||
public static final StructuredDataKey<UseCooldown> USE_COOLDOWN = new StructuredDataKey<>("use_cooldown", UseCooldown.TYPE);
|
||||
public static final StructuredDataKey<Unit> FIRE_RESISTANT = new StructuredDataKey<>("fire_resistant", Types.EMPTY);
|
||||
public static final StructuredDataKey<DamageResistant> DAMAGE_RESISTANT = new StructuredDataKey<>("damage_resistant", DamageResistant.TYPE);
|
||||
public static final StructuredDataKey<ToolProperties> TOOL = new StructuredDataKey<>("tool", ToolProperties.TYPE);
|
||||
public static final StructuredDataKey<Integer> ENCHANTABLE = new StructuredDataKey<>("enchantable", Types.VAR_INT);
|
||||
public static final StructuredDataKey<Equippable> EQUIPPABLE = new StructuredDataKey<>("equippable", Equippable.TYPE);
|
||||
public static final StructuredDataKey<HolderSet> REPAIRABLE = new StructuredDataKey<>("repairable", Types.HOLDER_SET);
|
||||
public static final StructuredDataKey<Unit> GLIDER = new StructuredDataKey<>("glider", Types.EMPTY);
|
||||
public static final StructuredDataKey<String> TOOLTIP_STYLE = new StructuredDataKey<>("tooltip_style", Types.STRING);
|
||||
public static final StructuredDataKey<DeathProtection> DEATH_PROTECTION = new StructuredDataKey<>("death_protection", DeathProtection.TYPE);
|
||||
public static final StructuredDataKey<Enchantments> STORED_ENCHANTMENTS = new StructuredDataKey<>("stored_enchantments", Enchantments.TYPE);
|
||||
public static final StructuredDataKey<DyedColor> DYED_COLOR = new StructuredDataKey<>("dyed_color", DyedColor.TYPE);
|
||||
public static final StructuredDataKey<Integer> MAP_COLOR = new StructuredDataKey<>("map_color", Types.INT);
|
||||
@@ -90,9 +111,12 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<Integer> MAP_POST_PROCESSING = new StructuredDataKey<>("map_post_processing", Types.VAR_INT);
|
||||
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_20_5 = new StructuredDataKey<>("charged_projectiles", Types1_20_5.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21 = new StructuredDataKey<>("charged_projectiles", Types1_21.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CHARGED_PROJECTILES1_21_2 = new StructuredDataKey<>("charged_projectiles", Types1_21_2.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_20_5 = new StructuredDataKey<>("bundle_contents", Types1_20_5.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21 = new StructuredDataKey<>("bundle_contents", Types1_21.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<PotionContents> POTION_CONTENTS = new StructuredDataKey<>("potion_contents", PotionContents.TYPE);
|
||||
public static final StructuredDataKey<Item[]> BUNDLE_CONTENTS1_21_2 = new StructuredDataKey<>("bundle_contents", Types1_21_2.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_20_5 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_20_5);
|
||||
public static final StructuredDataKey<PotionContents> POTION_CONTENTS1_21_2 = new StructuredDataKey<>("potion_contents", PotionContents.TYPE1_21_2);
|
||||
public static final StructuredDataKey<SuspiciousStewEffect[]> SUSPICIOUS_STEW_EFFECTS = new StructuredDataKey<>("suspicious_stew_effects", SuspiciousStewEffect.ARRAY_TYPE);
|
||||
public static final StructuredDataKey<FilterableString[]> WRITABLE_BOOK_CONTENT = new StructuredDataKey<>("writable_book_content", FilterableString.ARRAY_TYPE);
|
||||
public static final StructuredDataKey<WrittenBook> WRITTEN_BOOK_CONTENT = new StructuredDataKey<>("written_book_content", WrittenBook.TYPE);
|
||||
@@ -101,7 +125,8 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<CompoundTag> ENTITY_DATA = new StructuredDataKey<>("entity_data", Types.COMPOUND_TAG);
|
||||
public static final StructuredDataKey<CompoundTag> BUCKET_ENTITY_DATA = new StructuredDataKey<>("bucket_entity_data", Types.COMPOUND_TAG);
|
||||
public static final StructuredDataKey<CompoundTag> BLOCK_ENTITY_DATA = new StructuredDataKey<>("block_entity_data", Types.COMPOUND_TAG);
|
||||
public static final StructuredDataKey<Holder<Instrument>> INSTRUMENT = new StructuredDataKey<>("instrument", Instrument.TYPE);
|
||||
public static final StructuredDataKey<Holder<Instrument1_20_5>> INSTRUMENT1_20_5 = new StructuredDataKey<>("instrument", Instrument1_20_5.TYPE);
|
||||
public static final StructuredDataKey<Holder<Instrument1_21_2>> INSTRUMENT1_21_2 = new StructuredDataKey<>("instrument", Instrument1_21_2.TYPE);
|
||||
public static final StructuredDataKey<Integer> OMINOUS_BOTTLE_AMPLIFIER = new StructuredDataKey<>("ominous_bottle_amplifier", Types.VAR_INT);
|
||||
public static final StructuredDataKey<JukeboxPlayable> JUKEBOX_PLAYABLE = new StructuredDataKey<>("jukebox_playable", JukeboxPlayable.TYPE);
|
||||
public static final StructuredDataKey<Tag> RECIPES = new StructuredDataKey<>("recipes", Types.TAG);
|
||||
@@ -115,6 +140,7 @@ public record StructuredDataKey<T>(String identifier, Type<T> type) {
|
||||
public static final StructuredDataKey<PotDecorations> POT_DECORATIONS = new StructuredDataKey<>("pot_decorations", PotDecorations.TYPE);
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_20_5 = new StructuredDataKey<>("container", Types1_20_5.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_21 = new StructuredDataKey<>("container", Types1_21.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<Item[]> CONTAINER1_21_2 = new StructuredDataKey<>("container", Types1_21_2.ITEM_ARRAY);
|
||||
public static final StructuredDataKey<BlockStateProperties> BLOCK_STATE = new StructuredDataKey<>("block_state", BlockStateProperties.TYPE);
|
||||
public static final StructuredDataKey<Bee[]> BEES = new StructuredDataKey<>("bees", Bee.ARRAY_TYPE);
|
||||
public static final StructuredDataKey<Tag> LOCK = new StructuredDataKey<>("lock", Types.TAG);
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ public class EntityTypes1_12 {
|
||||
|
||||
LIVING_ENTITY_BASE(ENTITY),
|
||||
ARMOR_STAND(30, LIVING_ENTITY_BASE),
|
||||
PLAYER(ENTITY), // Needed for entity (un)tracking
|
||||
PLAYER(LIVING_ENTITY_BASE), // Needed for entity (un)tracking
|
||||
|
||||
// Living entities as a larger subclass
|
||||
LIVING_ENTITY(LIVING_ENTITY_BASE),
|
||||
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.entities;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.util.EntityTypeUtil;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
import java.util.Locale;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public enum EntityTypes1_21_2 implements EntityType {
|
||||
|
||||
ENTITY(null, null),
|
||||
|
||||
AREA_EFFECT_CLOUD(ENTITY),
|
||||
END_CRYSTAL(ENTITY),
|
||||
EVOKER_FANGS(ENTITY),
|
||||
EXPERIENCE_ORB(ENTITY),
|
||||
EYE_OF_ENDER(ENTITY),
|
||||
FALLING_BLOCK(ENTITY),
|
||||
ITEM(ENTITY),
|
||||
TNT(ENTITY),
|
||||
OMINOUS_ITEM_SPAWNER(ENTITY),
|
||||
MARKER(ENTITY),
|
||||
LIGHTNING_BOLT(ENTITY),
|
||||
INTERACTION(ENTITY),
|
||||
|
||||
DISPLAY(ENTITY, null),
|
||||
BLOCK_DISPLAY(DISPLAY),
|
||||
ITEM_DISPLAY(DISPLAY),
|
||||
TEXT_DISPLAY(DISPLAY),
|
||||
|
||||
// Hanging entities
|
||||
HANGING_ENTITY(ENTITY, null),
|
||||
LEASH_KNOT(HANGING_ENTITY),
|
||||
PAINTING(HANGING_ENTITY),
|
||||
ITEM_FRAME(HANGING_ENTITY),
|
||||
GLOW_ITEM_FRAME(ITEM_FRAME),
|
||||
|
||||
// Projectiles
|
||||
PROJECTILE(ENTITY, null),
|
||||
ITEM_PROJECTILE(PROJECTILE, null),
|
||||
SNOWBALL(ITEM_PROJECTILE),
|
||||
ENDER_PEARL(ITEM_PROJECTILE),
|
||||
EGG(ITEM_PROJECTILE),
|
||||
POTION(ITEM_PROJECTILE),
|
||||
EXPERIENCE_BOTTLE(ITEM_PROJECTILE),
|
||||
FIREWORK_ROCKET(PROJECTILE),
|
||||
LLAMA_SPIT(PROJECTILE),
|
||||
SHULKER_BULLET(PROJECTILE),
|
||||
FISHING_BOBBER(PROJECTILE),
|
||||
WITHER_SKULL(PROJECTILE),
|
||||
DRAGON_FIREBALL(PROJECTILE), // Doesn't actually inherit fireball
|
||||
|
||||
ABSTRACT_ARROW(PROJECTILE, null),
|
||||
ARROW(ABSTRACT_ARROW),
|
||||
SPECTRAL_ARROW(ABSTRACT_ARROW),
|
||||
TRIDENT(ABSTRACT_ARROW),
|
||||
|
||||
ABSTRACT_FIREBALL(ENTITY, null),
|
||||
FIREBALL(ABSTRACT_FIREBALL),
|
||||
SMALL_FIREBALL(ABSTRACT_FIREBALL),
|
||||
|
||||
ABSTRACT_WIND_CHARGE(PROJECTILE, null),
|
||||
WIND_CHARGE(ABSTRACT_WIND_CHARGE),
|
||||
BREEZE_WIND_CHARGE(ABSTRACT_WIND_CHARGE),
|
||||
|
||||
// Vehicles
|
||||
VEHICLE(ENTITY, null),
|
||||
|
||||
ABSTRACT_MINECART(VEHICLE, null),
|
||||
MINECART(ABSTRACT_MINECART),
|
||||
FURNACE_MINECART(ABSTRACT_MINECART),
|
||||
COMMAND_BLOCK_MINECART(ABSTRACT_MINECART),
|
||||
TNT_MINECART(ABSTRACT_MINECART),
|
||||
SPAWNER_MINECART(ABSTRACT_MINECART),
|
||||
|
||||
ABSTRACT_MINECART_CONTAINER(ABSTRACT_MINECART, null),
|
||||
CHEST_MINECART(ABSTRACT_MINECART_CONTAINER),
|
||||
HOPPER_MINECART(ABSTRACT_MINECART_CONTAINER),
|
||||
|
||||
ABSTRACT_BOAT(VEHICLE, null),
|
||||
ABSTRACT_CHEST_BOAT(ABSTRACT_BOAT, null),
|
||||
ACACIA_BOAT(ABSTRACT_BOAT),
|
||||
ACACIA_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
BAMBOO_CHEST_RAFT(ABSTRACT_CHEST_BOAT),
|
||||
BAMBOO_RAFT(ABSTRACT_BOAT),
|
||||
BIRCH_BOAT(ABSTRACT_BOAT),
|
||||
BIRCH_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
CHERRY_BOAT(ABSTRACT_BOAT),
|
||||
CHERRY_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
DARK_OAK_BOAT(ABSTRACT_BOAT),
|
||||
DARK_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
JUNGLE_BOAT(ABSTRACT_BOAT),
|
||||
JUNGLE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
MANGROVE_BOAT(ABSTRACT_BOAT),
|
||||
MANGROVE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
OAK_BOAT(ABSTRACT_BOAT),
|
||||
OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
PALE_OAK_BOAT(ABSTRACT_BOAT),
|
||||
PALE_OAK_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
SPRUCE_BOAT(ABSTRACT_BOAT),
|
||||
SPRUCE_CHEST_BOAT(ABSTRACT_CHEST_BOAT),
|
||||
|
||||
// Living entities as a larger subclass
|
||||
LIVING_ENTITY(ENTITY, null),
|
||||
ARMOR_STAND(LIVING_ENTITY),
|
||||
PLAYER(LIVING_ENTITY),
|
||||
|
||||
// Mobs as a larger subclass
|
||||
MOB(LIVING_ENTITY, null),
|
||||
ENDER_DRAGON(MOB),
|
||||
|
||||
SLIME(MOB),
|
||||
MAGMA_CUBE(SLIME),
|
||||
|
||||
// Ambient mobs
|
||||
AMBIENT_CREATURE(MOB, null),
|
||||
BAT(AMBIENT_CREATURE),
|
||||
|
||||
// Flying mobs
|
||||
FLYING_MOB(MOB, null),
|
||||
GHAST(FLYING_MOB),
|
||||
PHANTOM(FLYING_MOB),
|
||||
|
||||
// Pathfinder mobs and its subclasses
|
||||
PATHFINDER_MOB(MOB, null),
|
||||
ALLAY(PATHFINDER_MOB),
|
||||
|
||||
ABSTRACT_GOLEM(PATHFINDER_MOB, null),
|
||||
SNOW_GOLEM(ABSTRACT_GOLEM),
|
||||
IRON_GOLEM(ABSTRACT_GOLEM),
|
||||
SHULKER(ABSTRACT_GOLEM),
|
||||
|
||||
// Ageable mobs and (tamable) animals
|
||||
ABSTRACT_AGEABLE(PATHFINDER_MOB, null),
|
||||
ABSTRACT_VILLAGER(ABSTRACT_AGEABLE, null),
|
||||
VILLAGER(ABSTRACT_VILLAGER),
|
||||
WANDERING_TRADER(ABSTRACT_VILLAGER),
|
||||
|
||||
ABSTRACT_ANIMAL(ABSTRACT_AGEABLE, null),
|
||||
AXOLOTL(ABSTRACT_ANIMAL),
|
||||
CHICKEN(ABSTRACT_ANIMAL),
|
||||
PANDA(ABSTRACT_ANIMAL),
|
||||
PIG(ABSTRACT_ANIMAL),
|
||||
POLAR_BEAR(ABSTRACT_ANIMAL),
|
||||
RABBIT(ABSTRACT_ANIMAL),
|
||||
SHEEP(ABSTRACT_ANIMAL),
|
||||
BEE(ABSTRACT_ANIMAL),
|
||||
TURTLE(ABSTRACT_ANIMAL),
|
||||
FOX(ABSTRACT_ANIMAL),
|
||||
FROG(ABSTRACT_ANIMAL),
|
||||
GOAT(ABSTRACT_ANIMAL),
|
||||
HOGLIN(ABSTRACT_ANIMAL),
|
||||
STRIDER(ABSTRACT_ANIMAL),
|
||||
SNIFFER(ABSTRACT_ANIMAL),
|
||||
ARMADILLO(ABSTRACT_ANIMAL),
|
||||
|
||||
COW(ABSTRACT_ANIMAL),
|
||||
MOOSHROOM(COW),
|
||||
|
||||
TAMABLE_ANIMAL(ABSTRACT_ANIMAL, null),
|
||||
CAT(TAMABLE_ANIMAL),
|
||||
OCELOT(TAMABLE_ANIMAL),
|
||||
WOLF(TAMABLE_ANIMAL),
|
||||
PARROT(TAMABLE_ANIMAL),
|
||||
|
||||
ABSTRACT_HORSE(ABSTRACT_ANIMAL, null),
|
||||
HORSE(ABSTRACT_HORSE),
|
||||
SKELETON_HORSE(ABSTRACT_HORSE),
|
||||
ZOMBIE_HORSE(ABSTRACT_HORSE),
|
||||
CAMEL(ABSTRACT_HORSE),
|
||||
|
||||
ABSTRACT_CHESTED_HORSE(ABSTRACT_HORSE, null),
|
||||
DONKEY(ABSTRACT_CHESTED_HORSE),
|
||||
MULE(ABSTRACT_CHESTED_HORSE),
|
||||
LLAMA(ABSTRACT_CHESTED_HORSE),
|
||||
TRADER_LLAMA(LLAMA),
|
||||
|
||||
// Monsters
|
||||
ABSTRACT_MONSTER(PATHFINDER_MOB, null),
|
||||
BLAZE(ABSTRACT_MONSTER),
|
||||
CREEPER(ABSTRACT_MONSTER),
|
||||
ENDERMITE(ABSTRACT_MONSTER),
|
||||
ENDERMAN(ABSTRACT_MONSTER),
|
||||
GIANT(ABSTRACT_MONSTER),
|
||||
SILVERFISH(ABSTRACT_MONSTER),
|
||||
VEX(ABSTRACT_MONSTER),
|
||||
WITHER(ABSTRACT_MONSTER),
|
||||
BREEZE(ABSTRACT_MONSTER),
|
||||
ZOGLIN(ABSTRACT_MONSTER),
|
||||
WARDEN(ABSTRACT_MONSTER),
|
||||
CREAKING(ABSTRACT_MONSTER),
|
||||
CREAKING_TRANSIENT(ABSTRACT_MONSTER),
|
||||
|
||||
ABSTRACT_SKELETON(ABSTRACT_MONSTER, null),
|
||||
SKELETON(ABSTRACT_SKELETON),
|
||||
STRAY(ABSTRACT_SKELETON),
|
||||
WITHER_SKELETON(ABSTRACT_SKELETON),
|
||||
BOGGED(ABSTRACT_SKELETON),
|
||||
|
||||
ZOMBIE(ABSTRACT_MONSTER),
|
||||
DROWNED(ZOMBIE),
|
||||
HUSK(ZOMBIE),
|
||||
ZOMBIFIED_PIGLIN(ZOMBIE),
|
||||
ZOMBIE_VILLAGER(ZOMBIE),
|
||||
|
||||
GUARDIAN(ABSTRACT_MONSTER),
|
||||
ELDER_GUARDIAN(GUARDIAN),
|
||||
|
||||
SPIDER(ABSTRACT_MONSTER),
|
||||
CAVE_SPIDER(SPIDER),
|
||||
|
||||
ABSTRACT_PIGLIN(ABSTRACT_MONSTER, null),
|
||||
PIGLIN(ABSTRACT_PIGLIN),
|
||||
PIGLIN_BRUTE(ABSTRACT_PIGLIN),
|
||||
|
||||
// Water mobs
|
||||
AGEABLE_WATER_CREATURE(ABSTRACT_AGEABLE, null),
|
||||
DOLPHIN(AGEABLE_WATER_CREATURE),
|
||||
|
||||
SQUID(AGEABLE_WATER_CREATURE),
|
||||
GLOW_SQUID(SQUID),
|
||||
|
||||
WATER_ANIMAL(PATHFINDER_MOB, null),
|
||||
ABSTRACT_FISH(WATER_ANIMAL, null),
|
||||
PUFFERFISH(ABSTRACT_FISH),
|
||||
TADPOLE(ABSTRACT_FISH),
|
||||
|
||||
ABSTRACT_SCHOOLING_FISH(ABSTRACT_FISH, null),
|
||||
COD(ABSTRACT_SCHOOLING_FISH),
|
||||
SALMON(ABSTRACT_SCHOOLING_FISH),
|
||||
TROPICAL_FISH(ABSTRACT_SCHOOLING_FISH),
|
||||
|
||||
// Raiders
|
||||
ABSTRACT_RAIDER(ABSTRACT_MONSTER, null),
|
||||
WITCH(ABSTRACT_RAIDER),
|
||||
RAVAGER(ABSTRACT_RAIDER),
|
||||
|
||||
ABSTRACT_ILLAGER(ABSTRACT_RAIDER, null),
|
||||
SPELLCASTER_ILLAGER(ABSTRACT_ILLAGER, null),
|
||||
VINDICATOR(ABSTRACT_ILLAGER),
|
||||
PILLAGER(ABSTRACT_ILLAGER),
|
||||
EVOKER(SPELLCASTER_ILLAGER),
|
||||
ILLUSIONER(SPELLCASTER_ILLAGER);
|
||||
|
||||
private static final EntityType[] TYPES = EntityTypeUtil.createSizedArray(values());
|
||||
private final EntityType parent;
|
||||
private final String identifier;
|
||||
private int id = -1;
|
||||
|
||||
EntityTypes1_21_2(final EntityType parent) {
|
||||
this.parent = parent;
|
||||
this.identifier = Key.namespaced(name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
EntityTypes1_21_2(final EntityType parent, @Nullable final String identifier) {
|
||||
this.parent = parent;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
if (id == -1) {
|
||||
throw new IllegalStateException("Ids have not been initialized yet (type " + name() + ")");
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String identifier() {
|
||||
Preconditions.checkArgument(identifier != null, "Called identifier method on abstract type");
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable EntityType getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAbstractType() {
|
||||
return identifier == null;
|
||||
}
|
||||
|
||||
public static EntityType getTypeFromId(final int typeId) {
|
||||
return EntityTypeUtil.getTypeFromId(TYPES, typeId, ENTITY);
|
||||
}
|
||||
|
||||
public static void initialize(final Protocol<?, ?, ?, ?> protocol) {
|
||||
EntityTypeUtil.initialize(values(), TYPES, protocol, (type, id) -> type.id = id);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -99,7 +99,7 @@ public class EntityTypes1_9 {
|
||||
|
||||
LIVING_ENTITY_BASE(ENTITY),
|
||||
ARMOR_STAND(30, LIVING_ENTITY_BASE),
|
||||
PLAYER(ENTITY), // Needed for entity (un)tracking
|
||||
PLAYER(LIVING_ENTITY_BASE), // Needed for entity (un)tracking
|
||||
|
||||
// Living entities as a larger subclass
|
||||
LIVING_ENTITY(48, LIVING_ENTITY_BASE),
|
||||
|
||||
+5
-3
@@ -26,10 +26,11 @@ import com.viaversion.viaversion.api.minecraft.PaintingVariant;
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.minecraft.WolfVariant;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityDataType;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
|
||||
public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
|
||||
|
||||
@@ -40,7 +41,7 @@ public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
|
||||
public final EntityDataType stringType = add(4, Types.STRING);
|
||||
public final EntityDataType componentType = add(5, Types.TAG);
|
||||
public final EntityDataType optionalComponentType = add(6, Types.OPTIONAL_TAG);
|
||||
public final EntityDataType itemType = add(7, Types1_21.ITEM);
|
||||
public final EntityDataType itemType;
|
||||
public final EntityDataType booleanType = add(8, Types.BOOLEAN);
|
||||
public final EntityDataType rotationsType = add(9, Types.ROTATIONS);
|
||||
public final EntityDataType blockPositionType = add(10, Types.BLOCK_POSITION1_14);
|
||||
@@ -65,8 +66,9 @@ public final class EntityDataTypes1_21 extends AbstractEntityDataTypes {
|
||||
public final EntityDataType vector3FType = add(29, Types.VECTOR3F);
|
||||
public final EntityDataType quaternionType = add(30, Types.QUATERNION);
|
||||
|
||||
public EntityDataTypes1_21(final ParticleType particleType, final ArrayType<Particle> particlesType) {
|
||||
public EntityDataTypes1_21(final Type<Item> itemType, final ParticleType particleType, final ArrayType<Particle> particlesType) {
|
||||
super(31);
|
||||
this.itemType = add(7, itemType);
|
||||
this.particleType = add(17, particleType);
|
||||
this.particlesType = add(18, particlesType);
|
||||
}
|
||||
|
||||
+10
@@ -26,6 +26,7 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean showInTooltip) {
|
||||
|
||||
@@ -44,6 +45,15 @@ public record AttributeModifiers1_21(AttributeModifier[] modifiers, boolean show
|
||||
}
|
||||
};
|
||||
|
||||
public AttributeModifiers1_21 rewrite(final Int2IntFunction rewriteFunction) {
|
||||
final AttributeModifier[] modifiers = new AttributeModifier[this.modifiers.length];
|
||||
for (int i = 0; i < this.modifiers.length; i++) {
|
||||
final AttributeModifier modifier = this.modifiers[i];
|
||||
modifiers[i] = new AttributeModifier(rewriteFunction.applyAsInt(modifier.attribute()), modifier.modifier(), modifier.slotType());
|
||||
}
|
||||
return new AttributeModifiers1_21(modifiers, showInTooltip);
|
||||
}
|
||||
|
||||
public record AttributeModifier(int attribute, ModifierData modifier, int slotType) {
|
||||
|
||||
public static final Type<AttributeModifier> TYPE = new Type<>(AttributeModifier.class) {
|
||||
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public record Consumable1_21_2(float consumeSeconds, int animationType, Holder<SoundEvent> sound,
|
||||
boolean hasConsumeParticles, ConsumeEffect<?>[] consumeEffects) {
|
||||
|
||||
public static final Type<?>[] EFFECT_TYPES = {
|
||||
ApplyStatusEffects.TYPE,
|
||||
Types.HOLDER_SET, // remove effects
|
||||
Types.EMPTY, // clear all effects
|
||||
Types.FLOAT, // teleport randomly
|
||||
Types.SOUND_EVENT // play sound
|
||||
};
|
||||
|
||||
public static final Type<Consumable1_21_2> TYPE = new Type<>(Consumable1_21_2.class) {
|
||||
@Override
|
||||
public Consumable1_21_2 read(final ByteBuf buffer) {
|
||||
final float consumeSeconds = buffer.readFloat();
|
||||
final int animationType = Types.VAR_INT.readPrimitive(buffer);
|
||||
final Holder<SoundEvent> sound = Types.SOUND_EVENT.read(buffer);
|
||||
final boolean hasConsumeParticles = buffer.readBoolean();
|
||||
final ConsumeEffect<?>[] consumeEffects = ConsumeEffect.ARRAY_TYPE.read(buffer);
|
||||
return new Consumable1_21_2(consumeSeconds, animationType, sound, hasConsumeParticles, consumeEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final Consumable1_21_2 value) {
|
||||
buffer.writeFloat(value.consumeSeconds);
|
||||
Types.VAR_INT.writePrimitive(buffer, value.animationType);
|
||||
Types.SOUND_EVENT.write(buffer, value.sound);
|
||||
buffer.writeBoolean(value.hasConsumeParticles);
|
||||
ConsumeEffect.ARRAY_TYPE.write(buffer, value.consumeEffects);
|
||||
}
|
||||
};
|
||||
|
||||
public record ConsumeEffect<T>(int id, Type<T> type, T value) {
|
||||
|
||||
public static final Type<ConsumeEffect<?>> TYPE = new Type<>(ConsumeEffect.class) {
|
||||
@Override
|
||||
public ConsumeEffect<?> read(final ByteBuf buffer) {
|
||||
// Oh no...
|
||||
final int effectType = Types.VAR_INT.readPrimitive(buffer);
|
||||
final Type<?> type = EFFECT_TYPES[effectType];
|
||||
final Object value = type.read(buffer);
|
||||
return ConsumeEffect.of(effectType, type, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final ConsumeEffect<?> value) {
|
||||
Types.VAR_INT.writePrimitive(buffer, value.id);
|
||||
value.writeValue(buffer);
|
||||
}
|
||||
};
|
||||
public static final Type<ConsumeEffect<?>[]> ARRAY_TYPE = new ArrayType<>(TYPE);
|
||||
|
||||
static <T> ConsumeEffect<T> of(final int id, final Type<T> type, final Object value) {
|
||||
//noinspection unchecked
|
||||
return new ConsumeEffect<>(id, type, (T) value);
|
||||
}
|
||||
|
||||
void writeValue(final ByteBuf buf) {
|
||||
this.type.write(buf, this.value);
|
||||
}
|
||||
}
|
||||
|
||||
public record ApplyStatusEffects(PotionEffect[] effects, float probability) {
|
||||
|
||||
public static final Type<ApplyStatusEffects> TYPE = new Type<>(ApplyStatusEffects.class) {
|
||||
@Override
|
||||
public ApplyStatusEffects read(final ByteBuf buffer) {
|
||||
final PotionEffect[] effects = PotionEffect.ARRAY_TYPE.read(buffer);
|
||||
final float probability = buffer.readFloat();
|
||||
return new ApplyStatusEffects(effects, probability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final ApplyStatusEffects value) {
|
||||
PotionEffect.ARRAY_TYPE.write(buffer, value.effects);
|
||||
buffer.writeFloat(value.probability);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+7
-20
@@ -25,32 +25,19 @@ package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public record MapDecorations(Map<String, MapDecoration> decorations) {
|
||||
public record DamageResistant(String typesTagKey) {
|
||||
|
||||
public static final Type<MapDecorations> TYPE = new Type<>(MapDecorations.class) {
|
||||
public static final Type<DamageResistant> TYPE = new Type<>(DamageResistant.class) {
|
||||
@Override
|
||||
public MapDecorations read(final ByteBuf buffer) {
|
||||
final Object2ObjectMap<String, MapDecoration> decorations = new Object2ObjectOpenHashMap<>();
|
||||
final int size = Types.VAR_INT.readPrimitive(buffer);
|
||||
for (int i = 0; i < size; i++) {
|
||||
final String id = Types.STRING.read(buffer);
|
||||
final MapDecoration decoration = MapDecoration.TYPE.read(buffer);
|
||||
decorations.put(id, decoration);
|
||||
}
|
||||
return new MapDecorations(decorations);
|
||||
public DamageResistant read(final ByteBuf buffer) {
|
||||
final String typesTagKey = Types.STRING.read(buffer);
|
||||
return new DamageResistant(typesTagKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final MapDecorations value) {
|
||||
Types.VAR_INT.writePrimitive(buffer, value.decorations.size());
|
||||
for (final Map.Entry<String, MapDecoration> entry : value.decorations.entrySet()) {
|
||||
Types.STRING.write(buffer, entry.getKey());
|
||||
MapDecoration.TYPE.write(buffer, entry.getValue());
|
||||
}
|
||||
public void write(final ByteBuf buffer, final DamageResistant value) {
|
||||
Types.STRING.write(buffer, value.typesTagKey());
|
||||
}
|
||||
};
|
||||
}
|
||||
+9
-12
@@ -22,26 +22,23 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Consumable1_21_2.ConsumeEffect;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public record FoodEffect(PotionEffect effect, float probability) {
|
||||
public record DeathProtection(ConsumeEffect<?>[] deathEffects) {
|
||||
|
||||
public static final Type<FoodEffect> TYPE = new Type<>(FoodEffect.class) {
|
||||
public static final Type<DeathProtection> TYPE = new Type<>(DeathProtection.class) {
|
||||
@Override
|
||||
public FoodEffect read(final ByteBuf buffer) {
|
||||
final PotionEffect effect = PotionEffect.TYPE.read(buffer);
|
||||
final float probability = buffer.readFloat();
|
||||
return new FoodEffect(effect, probability);
|
||||
public DeathProtection read(final ByteBuf buffer) {
|
||||
final ConsumeEffect<?>[] deathEffects = ConsumeEffect.ARRAY_TYPE.read(buffer);
|
||||
return new DeathProtection(deathEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final FoodEffect value) {
|
||||
PotionEffect.TYPE.write(buffer, value.effect);
|
||||
buffer.writeFloat(value.probability);
|
||||
public void write(final ByteBuf buffer, final DeathProtection value) {
|
||||
ConsumeEffect.ARRAY_TYPE.write(buffer, value.deathEffects);
|
||||
}
|
||||
};
|
||||
public static final Type<FoodEffect[]> ARRAY_TYPE = new ArrayType<>(TYPE);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.HolderSet;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record Equippable(int equipmentSlot, Holder<SoundEvent> soundEvent, @Nullable String model,
|
||||
@Nullable String cameraOverlay, @Nullable HolderSet allowedEntities, boolean dispensable,
|
||||
boolean swappable, boolean damageOnHurt) {
|
||||
|
||||
public static final Type<Equippable> TYPE = new Type<>(Equippable.class) {
|
||||
@Override
|
||||
public Equippable read(final ByteBuf buffer) {
|
||||
final int equipmentSlot = Types.VAR_INT.readPrimitive(buffer);
|
||||
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
|
||||
final String model = Types.OPTIONAL_STRING.read(buffer);
|
||||
final String cameraOverlay = Types.OPTIONAL_STRING.read(buffer);
|
||||
final HolderSet allowedEntities = Types.HOLDER_SET.read(buffer);
|
||||
final boolean dispensable = buffer.readBoolean();
|
||||
final boolean swappable = buffer.readBoolean();
|
||||
final boolean damageOnHurt = buffer.readBoolean();
|
||||
return new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final Equippable value) {
|
||||
Types.VAR_INT.writePrimitive(buffer, value.equipmentSlot());
|
||||
Types.SOUND_EVENT.write(buffer, value.soundEvent());
|
||||
Types.OPTIONAL_STRING.write(buffer, value.model());
|
||||
Types.OPTIONAL_STRING.write(buffer, value.cameraOverlay());
|
||||
Types.HOLDER_SET.write(buffer, value.allowedEntities());
|
||||
buffer.writeBoolean(value.dispensable());
|
||||
buffer.writeBoolean(value.swappable());
|
||||
buffer.writeBoolean(value.damageOnHurt());
|
||||
}
|
||||
};
|
||||
|
||||
public Equippable rewrite(final Int2IntFunction soundIdRewriter) {
|
||||
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriter);
|
||||
return soundEvent == this.soundEvent ? this : new Equippable(equipmentSlot, soundEvent, model, cameraOverlay, allowedEntities, dispensable, swappable, damageOnHurt);
|
||||
}
|
||||
}
|
||||
+30
-10
@@ -25,25 +25,26 @@ package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public record FoodProperties(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
|
||||
Item usingConvertsTo, FoodEffect[] possibleEffects) {
|
||||
public record FoodProperties1_20_5(int nutrition, float saturationModifier, boolean canAlwaysEat, float eatSeconds,
|
||||
Item usingConvertsTo, FoodEffect[] possibleEffects) {
|
||||
|
||||
public static final Type<FoodProperties> TYPE1_20_5 = new Type<>(FoodProperties.class) {
|
||||
public static final Type<FoodProperties1_20_5> TYPE1_20_5 = new Type<>(FoodProperties1_20_5.class) {
|
||||
@Override
|
||||
public FoodProperties read(final ByteBuf buffer) {
|
||||
public FoodProperties1_20_5 read(final ByteBuf buffer) {
|
||||
final int nutrition = Types.VAR_INT.readPrimitive(buffer);
|
||||
final float saturationModifier = buffer.readFloat();
|
||||
final boolean canAlwaysEat = buffer.readBoolean();
|
||||
final float eatSeconds = buffer.readFloat();
|
||||
final FoodEffect[] possibleEffects = FoodEffect.ARRAY_TYPE.read(buffer);
|
||||
return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, null, possibleEffects);
|
||||
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, null, possibleEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final FoodProperties value) {
|
||||
public void write(final ByteBuf buffer, final FoodProperties1_20_5 value) {
|
||||
Types.VAR_INT.writePrimitive(buffer, value.nutrition);
|
||||
buffer.writeFloat(value.saturationModifier);
|
||||
buffer.writeBoolean(value.canAlwaysEat);
|
||||
@@ -51,20 +52,20 @@ public record FoodProperties(int nutrition, float saturationModifier, boolean ca
|
||||
FoodEffect.ARRAY_TYPE.write(buffer, value.possibleEffects);
|
||||
}
|
||||
};
|
||||
public static final Type<FoodProperties> TYPE1_21 = new Type<FoodProperties>(FoodProperties.class) {
|
||||
public static final Type<FoodProperties1_20_5> TYPE1_21 = new Type<>(FoodProperties1_20_5.class) {
|
||||
@Override
|
||||
public FoodProperties read(final ByteBuf buffer) {
|
||||
public FoodProperties1_20_5 read(final ByteBuf buffer) {
|
||||
final int nutrition = Types.VAR_INT.readPrimitive(buffer);
|
||||
final float saturationModifier = buffer.readFloat();
|
||||
final boolean canAlwaysEat = buffer.readBoolean();
|
||||
final float eatSeconds = buffer.readFloat();
|
||||
final Item usingConvertsTo = Types1_21.OPTIONAL_ITEM.read(buffer);
|
||||
final FoodEffect[] possibleEffects = FoodEffect.ARRAY_TYPE.read(buffer);
|
||||
return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo, possibleEffects);
|
||||
return new FoodProperties1_20_5(nutrition, saturationModifier, canAlwaysEat, eatSeconds, usingConvertsTo, possibleEffects);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final FoodProperties value) {
|
||||
public void write(final ByteBuf buffer, final FoodProperties1_20_5 value) {
|
||||
Types.VAR_INT.writePrimitive(buffer, value.nutrition);
|
||||
buffer.writeFloat(value.saturationModifier);
|
||||
buffer.writeBoolean(value.canAlwaysEat);
|
||||
@@ -73,4 +74,23 @@ public record FoodProperties(int nutrition, float saturationModifier, boolean ca
|
||||
FoodEffect.ARRAY_TYPE.write(buffer, value.possibleEffects);
|
||||
}
|
||||
};
|
||||
|
||||
public record FoodEffect(PotionEffect effect, float probability) {
|
||||
|
||||
public static final Type<FoodEffect> TYPE = new Type<>(FoodEffect.class) {
|
||||
@Override
|
||||
public FoodEffect read(final ByteBuf buffer) {
|
||||
final PotionEffect effect = PotionEffect.TYPE.read(buffer);
|
||||
final float probability = buffer.readFloat();
|
||||
return new FoodEffect(effect, probability);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final FoodEffect value) {
|
||||
PotionEffect.TYPE.write(buffer, value.effect);
|
||||
buffer.writeFloat(value.probability);
|
||||
}
|
||||
};
|
||||
public static final Type<FoodEffect[]> ARRAY_TYPE = new ArrayType<>(TYPE);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public record FoodProperties1_21_2(int nutrition, float saturationModifier, boolean canAlwaysEat) {
|
||||
|
||||
public static final Type<FoodProperties1_21_2> TYPE = new Type<>(FoodProperties1_21_2.class) {
|
||||
@Override
|
||||
public FoodProperties1_21_2 read(final ByteBuf buffer) {
|
||||
final int nutrition = Types.VAR_INT.readPrimitive(buffer);
|
||||
final float saturationModifier = buffer.readFloat();
|
||||
final boolean canAlwaysEat = buffer.readBoolean();
|
||||
return new FoodProperties1_21_2(nutrition, saturationModifier, canAlwaysEat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final FoodProperties1_21_2 value) {
|
||||
Types.VAR_INT.writePrimitive(buffer, value.nutrition);
|
||||
buffer.writeFloat(value.saturationModifier);
|
||||
buffer.writeBoolean(value.canAlwaysEat);
|
||||
}
|
||||
};
|
||||
}
|
||||
+12
-7
@@ -27,24 +27,29 @@ import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.misc.HolderType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
public record Instrument(Holder<SoundEvent> soundEvent, int useDuration, float range) {
|
||||
public record Instrument1_20_5(Holder<SoundEvent> soundEvent, int useDuration, float range) {
|
||||
|
||||
public static final HolderType<Instrument> TYPE = new HolderType<>() {
|
||||
public static final HolderType<Instrument1_20_5> TYPE = new HolderType<>() {
|
||||
@Override
|
||||
public Instrument readDirect(final ByteBuf buffer) {
|
||||
public Instrument1_20_5 readDirect(final ByteBuf buffer) {
|
||||
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
|
||||
final int useDuration = Types.VAR_INT.readPrimitive(buffer);
|
||||
final float range = buffer.readFloat();
|
||||
return new Instrument(soundEvent, useDuration, range);
|
||||
final float range = Types.FLOAT.readPrimitive(buffer);
|
||||
return new Instrument1_20_5(soundEvent, useDuration, range);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDirect(final ByteBuf buffer, final Instrument value) {
|
||||
public void writeDirect(final ByteBuf buffer, final Instrument1_20_5 value) {
|
||||
Types.SOUND_EVENT.write(buffer, value.soundEvent());
|
||||
Types.VAR_INT.writePrimitive(buffer, value.useDuration());
|
||||
buffer.writeFloat(value.range());
|
||||
Types.FLOAT.writePrimitive(buffer, value.range());
|
||||
}
|
||||
};
|
||||
|
||||
public Instrument1_20_5 rewrite(final Int2IntFunction soundIdRewriteFunction) {
|
||||
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
|
||||
return soundEvent == this.soundEvent ? this : new Instrument1_20_5(soundEvent, useDuration, range);
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.nbt.tag.Tag;
|
||||
import com.viaversion.viaversion.api.minecraft.Holder;
|
||||
import com.viaversion.viaversion.api.minecraft.SoundEvent;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.misc.HolderType;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
public record Instrument1_21_2(Holder<SoundEvent> soundEvent, float useDuration, float range, Tag description) {
|
||||
|
||||
public static final HolderType<Instrument1_21_2> TYPE = new HolderType<>() {
|
||||
@Override
|
||||
public Instrument1_21_2 readDirect(final ByteBuf buffer) {
|
||||
final Holder<SoundEvent> soundEvent = Types.SOUND_EVENT.read(buffer);
|
||||
final float useDuration = Types.FLOAT.readPrimitive(buffer);
|
||||
final float range = Types.FLOAT.readPrimitive(buffer);
|
||||
final Tag description = Types.TAG.read(buffer);
|
||||
return new Instrument1_21_2(soundEvent, useDuration, range, description);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDirect(final ByteBuf buffer, final Instrument1_21_2 value) {
|
||||
Types.SOUND_EVENT.write(buffer, value.soundEvent());
|
||||
Types.FLOAT.writePrimitive(buffer, value.useDuration());
|
||||
Types.FLOAT.writePrimitive(buffer, value.range());
|
||||
Types.TAG.write(buffer, value.description());
|
||||
}
|
||||
};
|
||||
|
||||
public Instrument1_21_2 rewrite(final Int2IntFunction soundIdRewriteFunction) {
|
||||
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
|
||||
return soundEvent == this.soundEvent ? this : new Instrument1_21_2(soundEvent, useDuration, range, description);
|
||||
}
|
||||
}
|
||||
+20
@@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.misc.HolderType;
|
||||
import com.viaversion.viaversion.util.Either;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntFunction;
|
||||
|
||||
public record JukeboxPlayable(Either<Holder<JukeboxSong>, String> song, boolean showInTooltip) {
|
||||
|
||||
@@ -56,6 +57,20 @@ public record JukeboxPlayable(Either<Holder<JukeboxSong>, String> song, boolean
|
||||
}
|
||||
};
|
||||
|
||||
public JukeboxPlayable rewrite(final Int2IntFunction soundIdRewriteFunction) {
|
||||
if (song.isRight()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
final Holder<JukeboxSong> songHolder = this.song.left();
|
||||
if (songHolder.hasId()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
final JukeboxSong rewrittenSong = songHolder.value().rewrite(soundIdRewriteFunction);
|
||||
return rewrittenSong == songHolder.value() ? this : new JukeboxPlayable(Holder.of(rewrittenSong), showInTooltip);
|
||||
}
|
||||
|
||||
public record JukeboxSong(Holder<SoundEvent> soundEvent, Tag description,
|
||||
float lengthInSeconds, int comparatorOutput) {
|
||||
|
||||
@@ -77,5 +92,10 @@ public record JukeboxPlayable(Either<Holder<JukeboxSong>, String> song, boolean
|
||||
Types.VAR_INT.writePrimitive(buffer, value.comparatorOutput);
|
||||
}
|
||||
};
|
||||
|
||||
public JukeboxSong rewrite(final Int2IntFunction soundIdRewriteFunction) {
|
||||
final Holder<SoundEvent> soundEvent = this.soundEvent.updateId(soundIdRewriteFunction);
|
||||
return soundEvent == this.soundEvent ? this : new JukeboxSong(soundEvent, description, lengthInSeconds, comparatorOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
+35
-3
@@ -27,15 +27,20 @@ import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record PotionContents(@Nullable Integer potion, @Nullable Integer customColor, PotionEffect[] customEffects) {
|
||||
public record PotionContents(@Nullable Integer potion, @Nullable Integer customColor, PotionEffect[] customEffects,
|
||||
@Nullable String customName) {
|
||||
|
||||
public static final Type<PotionContents> TYPE = new Type<>(PotionContents.class) {
|
||||
public PotionContents(final @Nullable Integer potion, final @Nullable Integer customColor, final PotionEffect[] customEffects) {
|
||||
this(potion, customColor, customEffects, null);
|
||||
}
|
||||
|
||||
public static final Type<PotionContents> TYPE1_20_5 = new Type<>(PotionContents.class) {
|
||||
@Override
|
||||
public PotionContents read(final ByteBuf buffer) {
|
||||
final Integer potion = buffer.readBoolean() ? Types.VAR_INT.readPrimitive(buffer) : null;
|
||||
final Integer customColor = buffer.readBoolean() ? buffer.readInt() : null;
|
||||
final PotionEffect[] customEffects = PotionEffect.ARRAY_TYPE.read(buffer);
|
||||
return new PotionContents(potion, customColor, customEffects);
|
||||
return new PotionContents(potion, customColor, customEffects, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -53,4 +58,31 @@ public record PotionContents(@Nullable Integer potion, @Nullable Integer customC
|
||||
PotionEffect.ARRAY_TYPE.write(buffer, value.customEffects);
|
||||
}
|
||||
};
|
||||
|
||||
public static final Type<PotionContents> TYPE1_21_2 = new Type<>(PotionContents.class) {
|
||||
@Override
|
||||
public PotionContents read(final ByteBuf buffer) {
|
||||
final Integer potion = buffer.readBoolean() ? Types.VAR_INT.readPrimitive(buffer) : null;
|
||||
final Integer customColor = buffer.readBoolean() ? buffer.readInt() : null;
|
||||
final PotionEffect[] customEffects = PotionEffect.ARRAY_TYPE.read(buffer);
|
||||
final String customName = Types.OPTIONAL_STRING.read(buffer);
|
||||
return new PotionContents(potion, customColor, customEffects, customName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final PotionContents value) {
|
||||
buffer.writeBoolean(value.potion != null);
|
||||
if (value.potion != null) {
|
||||
Types.VAR_INT.writePrimitive(buffer, value.potion);
|
||||
}
|
||||
|
||||
buffer.writeBoolean(value.customColor != null);
|
||||
if (value.customColor != null) {
|
||||
buffer.writeInt(value.customColor);
|
||||
}
|
||||
|
||||
PotionEffect.ARRAY_TYPE.write(buffer, value.customEffects);
|
||||
Types.OPTIONAL_STRING.write(buffer, value.customName);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.item.data;
|
||||
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import java.util.function.Function;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public record UseCooldown(float seconds, @Nullable String cooldownGroup) {
|
||||
|
||||
public static final Type<UseCooldown> TYPE = new Type<>(UseCooldown.class) {
|
||||
@Override
|
||||
public UseCooldown read(final ByteBuf buffer) {
|
||||
final float seconds = buffer.readFloat();
|
||||
final String cooldownGroup = Types.OPTIONAL_STRING.read(buffer);
|
||||
return new UseCooldown(seconds, cooldownGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer, final UseCooldown value) {
|
||||
buffer.writeFloat(value.seconds());
|
||||
Types.OPTIONAL_STRING.write(buffer, value.cooldownGroup());
|
||||
}
|
||||
};
|
||||
|
||||
public UseCooldown rewrite(final Function<String, String> idRewriter) {
|
||||
if (cooldownGroup == null) {
|
||||
return this;
|
||||
}
|
||||
|
||||
final String mappedCooldownGroup = idRewriter.apply(cooldownGroup);
|
||||
return new UseCooldown(seconds, mappedCooldownGroup);
|
||||
}
|
||||
}
|
||||
@@ -198,6 +198,14 @@ 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();
|
||||
|
||||
@@ -25,6 +25,7 @@ package com.viaversion.viaversion.api.protocol;
|
||||
import com.google.common.collect.Range;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
@@ -73,13 +74,14 @@ public interface ProtocolManager {
|
||||
Protocol getBaseProtocol();
|
||||
|
||||
/**
|
||||
* Returns the base protocol for a specific server protocol version.
|
||||
* Returns the base protocols for a specific server and client protocol version.
|
||||
* The standard base protocols deal with status and login packets for userconnection initialization.
|
||||
*
|
||||
* @param clientVersion client protocol version
|
||||
* @param serverVersion server protocol version
|
||||
* @return base protocol for the given server protocol version if present, else null
|
||||
* @return base protocols for the given server and client protocol version
|
||||
*/
|
||||
@Nullable Protocol getBaseProtocol(ProtocolVersion serverVersion);
|
||||
List<Protocol> getBaseProtocols(@Nullable ProtocolVersion clientVersion, @Nullable ProtocolVersion serverVersion);
|
||||
|
||||
/**
|
||||
* Returns an immutable collection of registered protocols.
|
||||
@@ -120,11 +122,12 @@ public interface ProtocolManager {
|
||||
* Registers and initializes a base protocol. Base Protocols registered later have higher priority.
|
||||
* Only base protocol will always be added to pipeline.
|
||||
*
|
||||
* @param direction direction of the base protocol
|
||||
* @param baseProtocol base protocol to register
|
||||
* @param supportedProtocols protocol versions supported by the base protocol
|
||||
* @throws IllegalArgumentException if the protocol is not a base protocol as given by {@link Protocol#isBaseProtocol()}
|
||||
*/
|
||||
void registerBaseProtocol(Protocol baseProtocol, Range<ProtocolVersion> supportedProtocols);
|
||||
void registerBaseProtocol(Direction direction, Protocol baseProtocol, Range<ProtocolVersion> supportedProtocols);
|
||||
|
||||
/**
|
||||
* Calculates and returns the protocol path from a client protocol version to server protocol version.
|
||||
|
||||
@@ -145,6 +145,18 @@ public interface PacketWrapper {
|
||||
*/
|
||||
<T> T passthrough(Type<T> type) throws InformativeException;
|
||||
|
||||
/**
|
||||
* Take a value from the input and write to the output, mapping the output type.
|
||||
* This only works for types implementing {@link com.viaversion.viaversion.api.type.TypeConverter}, which is generally only the primitive wrapper types.
|
||||
*
|
||||
* @param type The type to read.
|
||||
* @param mappedType The type to write.
|
||||
* @param <T> The return type of the type you wish to pass through.
|
||||
* @return The type which was read/written.
|
||||
* @throws InformativeException If it failed to read or write
|
||||
*/
|
||||
<T> T passthroughAndMap(Type<?> type, Type<T> mappedType) throws InformativeException;
|
||||
|
||||
/**
|
||||
* Take all the inputs and write them to the output.
|
||||
*
|
||||
@@ -224,6 +236,14 @@ public interface PacketWrapper {
|
||||
*/
|
||||
void sendRaw() throws InformativeException;
|
||||
|
||||
/**
|
||||
* Sends this packet to the associated user, submitted to netty's event loop.
|
||||
* <b>Unlike {@link #sendFuture(Class)}, this method does not handle the pipeline with packet id and data changes.</b>
|
||||
*
|
||||
* @throws InformativeException if it fails to write
|
||||
*/
|
||||
ChannelFuture sendFutureRaw() throws InformativeException;
|
||||
|
||||
/**
|
||||
* Sends this packet to the associated user, submitted to netty's event loop.
|
||||
* <b>Unlike {@link #send(Class)}, this method does not handle the pipeline with packet id and data changes.</b>
|
||||
|
||||
+3
-3
@@ -54,7 +54,7 @@ public abstract class PacketHandlers implements PacketHandler {
|
||||
* @param type type to map
|
||||
*/
|
||||
public <T> void map(Type<T> type) {
|
||||
handler(wrapper -> wrapper.write(type, wrapper.read(type)));
|
||||
handler(wrapper -> wrapper.passthrough(type));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,8 +63,8 @@ public abstract class PacketHandlers implements PacketHandler {
|
||||
* @param oldType old type
|
||||
* @param newType new type
|
||||
*/
|
||||
public void map(Type oldType, Type newType) {
|
||||
handler(wrapper -> wrapper.write(newType, wrapper.read(oldType)));
|
||||
public void map(Type<?> oldType, Type<?> newType) {
|
||||
handler(wrapper -> wrapper.passthroughAndMap(oldType, newType));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
-6
@@ -43,7 +43,8 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||
private static final List<ProtocolVersion> VERSION_LIST = new ArrayList<>();
|
||||
|
||||
public static final ProtocolVersion v1_7_2 = register(4, "1.7.2-1.7.5", new SubVersionRange("1.7", 2, 5));
|
||||
@Deprecated(forRemoval=true) public static final ProtocolVersion v1_7_1 = v1_7_2;
|
||||
@Deprecated(forRemoval = true)
|
||||
public static final ProtocolVersion v1_7_1 = v1_7_2;
|
||||
public static final ProtocolVersion v1_7_6 = register(5, "1.7.6-1.7.10", new SubVersionRange("1.7", 6, 10));
|
||||
public static final ProtocolVersion v1_8 = register(47, "1.8.x", new SubVersionRange("1.8", 0, 9));
|
||||
public static final ProtocolVersion v1_9 = register(107, "1.9");
|
||||
@@ -84,9 +85,14 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||
public static final ProtocolVersion v1_20_2 = register(764, "1.20.2");
|
||||
public static final ProtocolVersion v1_20_3 = register(765, "1.20.3-1.20.4", new SubVersionRange("1.20", 3, 4));
|
||||
public static final ProtocolVersion v1_20_5 = register(766, "1.20.5-1.20.6", new SubVersionRange("1.20", 5, 6));
|
||||
public static final ProtocolVersion v1_21 = register(767, "1.21");
|
||||
public static final ProtocolVersion v1_21 = register(767, "1.21-1.21.1", new SubVersionRange("1.21", 0, 1));
|
||||
public static final ProtocolVersion v1_21_2 = register(768, "1.21.2-1.21.3", new SubVersionRange("1.21", 2, 3));
|
||||
public static final ProtocolVersion unknown = new ProtocolVersion(VersionType.SPECIAL, -1, -1, "UNKNOWN", null);
|
||||
|
||||
static {
|
||||
unknown.known = false;
|
||||
}
|
||||
|
||||
public static ProtocolVersion register(int version, String name) {
|
||||
return register(version, -1, name);
|
||||
}
|
||||
@@ -150,7 +156,11 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||
return protocolVersion;
|
||||
}
|
||||
}
|
||||
return new ProtocolVersion(VersionType.SPECIAL, version, -1, "Unknown (" + version + ")", null);
|
||||
|
||||
// Will be made nullable instead in the future...
|
||||
final ProtocolVersion unknown = new ProtocolVersion(versionType, version, -1, "Unknown (" + version + ")", null);
|
||||
unknown.known = false;
|
||||
return unknown;
|
||||
}
|
||||
|
||||
public static @NonNull ProtocolVersion getProtocol(final int version) {
|
||||
@@ -201,6 +211,8 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||
private final int snapshotVersion;
|
||||
private final String name;
|
||||
private final Set<String> includedVersions;
|
||||
@Deprecated // Remove when getProtocol is made nullable
|
||||
private boolean known = true;
|
||||
|
||||
/**
|
||||
* Constructs a new ProtocolVersion instance.
|
||||
@@ -285,12 +297,12 @@ public class ProtocolVersion implements Comparable<ProtocolVersion> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the protocol is set. Should only be unknown for unregistered protocols returned by {@link #getProtocol(int)}.
|
||||
* Returns whether the protocol version is {@link #unknown}. For checking if the protocol version is registered, use {@link #isRegistered(VersionType, int)}
|
||||
*
|
||||
* @return true if the protocol is set
|
||||
* @return true if the protocol version is unknown
|
||||
*/
|
||||
public boolean isKnown() {
|
||||
return version != -1;
|
||||
return known;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
package com.viaversion.viaversion.api.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
@@ -50,6 +51,8 @@ public interface ItemRewriter<T extends Protocol<?, ?, ?, ?>> extends Rewriter<T
|
||||
@Nullable
|
||||
Item handleItemToServer(UserConnection connection, @Nullable Item item);
|
||||
|
||||
void rewriteParticle(UserConnection connection, Particle particle);
|
||||
|
||||
/**
|
||||
* Returns the item type of the current protocol.
|
||||
*
|
||||
|
||||
@@ -189,7 +189,9 @@ public final class Types {
|
||||
public static final Type<PlayerMessageSignature> OPTIONAL_PLAYER_MESSAGE_SIGNATURE = new PlayerMessageSignatureType.OptionalPlayerMessageSignatureType();
|
||||
public static final Type<PlayerMessageSignature[]> PLAYER_MESSAGE_SIGNATURE_ARRAY = new ArrayType<>(PLAYER_MESSAGE_SIGNATURE);
|
||||
|
||||
public static final BitSetType PROFILE_ACTIONS_ENUM = new BitSetType(6);
|
||||
public static final BitSetType PROFILE_ACTIONS_ENUM1_19_3 = new BitSetType(6);
|
||||
public static final BitSetType PROFILE_ACTIONS_ENUM1_21_2 = new BitSetType(7);
|
||||
|
||||
public static final ByteArrayType SIGNATURE_BYTES = new ByteArrayType(256);
|
||||
public static final BitSetType ACKNOWLEDGED_BIT_SET = new BitSetType(20);
|
||||
public static final ByteArrayType.OptionalByteArrayType OPTIONAL_SIGNATURE_BYTES = new ByteArrayType.OptionalByteArrayType(256);
|
||||
|
||||
@@ -36,11 +36,19 @@ public class IntType extends Type<Integer> implements TypeConverter<Integer> {
|
||||
return buffer.readInt();
|
||||
}
|
||||
|
||||
public int readPrimitive(ByteBuf buffer) {
|
||||
return buffer.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ByteBuf buffer, Integer object) {
|
||||
buffer.writeInt(object);
|
||||
}
|
||||
|
||||
public void writePrimitive(ByteBuf buffer, int object) {
|
||||
buffer.writeInt(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer from(Object o) {
|
||||
if (o instanceof Number number) {
|
||||
|
||||
+7
@@ -87,5 +87,12 @@ public class StructuredDataType extends Type<StructuredData<?>> {
|
||||
types[id] = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DataFiller add(final StructuredDataKey<?>... keys) {
|
||||
for (final StructuredDataKey<?> key : keys) {
|
||||
add(key);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -77,6 +77,10 @@ public class ParticleType extends DynamicType<Particle> {
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Blue 0-1
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Scale 0.01-4
|
||||
};
|
||||
public static final DataReader<Particle> DUST1_21_2 = (buf, particle) -> {
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // RGB
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Scale 0.01-4
|
||||
};
|
||||
public static final DataReader<Particle> DUST_TRANSITION = (buf, particle) -> {
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Red 0-1
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Green 0-1
|
||||
@@ -86,6 +90,11 @@ public class ParticleType extends DynamicType<Particle> {
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Green
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Blue
|
||||
};
|
||||
public static final DataReader<Particle> DUST_TRANSITION1_21_2 = (buf, particle) -> {
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // From RGB
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // To RGB
|
||||
particle.add(Types.FLOAT, Types.FLOAT.readPrimitive(buf)); // Scale 0.01-4
|
||||
};
|
||||
public static final DataReader<Particle> VIBRATION = (buf, particle) -> {
|
||||
particle.add(Types.BLOCK_POSITION1_14, Types.BLOCK_POSITION1_14.read(buf)); // From block pos
|
||||
|
||||
@@ -136,7 +145,15 @@ public class ParticleType extends DynamicType<Particle> {
|
||||
public static final DataReader<Particle> SHRIEK = (buf, particle) -> {
|
||||
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Delay
|
||||
};
|
||||
public static final DataReader<Particle> COLOR = (buf, particle) -> particle.add(Types.INT, buf.readInt());
|
||||
public static final DataReader<Particle> COLOR = (buf, particle) -> {
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf));
|
||||
};
|
||||
public static final DataReader<Particle> TRAIL = (buf, particle) -> {
|
||||
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Target X
|
||||
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Target Y
|
||||
particle.add(Types.VAR_INT, Types.VAR_INT.readPrimitive(buf)); // Target Z
|
||||
particle.add(Types.INT, Types.INT.readPrimitive(buf)); // Color
|
||||
};
|
||||
|
||||
public static DataReader<Particle> item(Type<Item> item) {
|
||||
return (buf, particle) -> particle.add(item, item.read(buf));
|
||||
|
||||
@@ -50,7 +50,7 @@ public final class Types1_21 {
|
||||
|
||||
public static final ParticleType PARTICLE = new ParticleType();
|
||||
public static final ArrayType<Particle> PARTICLES = new ArrayType<>(PARTICLE);
|
||||
public static final EntityDataTypes1_21 ENTITY_DATA_TYPES = new EntityDataTypes1_21(PARTICLE, PARTICLES);
|
||||
public static final EntityDataTypes1_21 ENTITY_DATA_TYPES = new EntityDataTypes1_21(ITEM, PARTICLE, PARTICLES);
|
||||
public static final Type<EntityData> ENTITY_DATA = new EntityDataType(ENTITY_DATA_TYPES);
|
||||
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.version;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.Particle;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.EntityData;
|
||||
import com.viaversion.viaversion.api.minecraft.entitydata.types.EntityDataTypes1_21;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.ArrayType;
|
||||
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataListType;
|
||||
import com.viaversion.viaversion.api.type.types.entitydata.EntityDataType;
|
||||
import com.viaversion.viaversion.api.type.types.item.ItemCostType1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.item.ItemType1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.item.StructuredDataType;
|
||||
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
|
||||
import java.util.List;
|
||||
|
||||
// Most of these are only safe to use after protocol loading
|
||||
public final class Types1_21_2 {
|
||||
|
||||
public static final StructuredDataType STRUCTURED_DATA = new StructuredDataType();
|
||||
public static final Type<StructuredData<?>[]> STRUCTURED_DATA_ARRAY = new ArrayType<>(STRUCTURED_DATA);
|
||||
public static final ItemType1_20_5 ITEM = new ItemType1_20_5(STRUCTURED_DATA);
|
||||
public static final Type<Item> OPTIONAL_ITEM = ITEM.new OptionalItemType(); // Optional as in boolean prefixed, not via the amount
|
||||
public static final Type<Item[]> ITEM_ARRAY = new ArrayType<>(ITEM);
|
||||
public static final Type<Item> ITEM_COST = new ItemCostType1_20_5(STRUCTURED_DATA_ARRAY);
|
||||
public static final Type<Item> OPTIONAL_ITEM_COST = new ItemCostType1_20_5.OptionalItemCostType(ITEM_COST);
|
||||
|
||||
public static final ParticleType PARTICLE = new ParticleType();
|
||||
public static final ArrayType<Particle> PARTICLES = new ArrayType<>(PARTICLE);
|
||||
public static final EntityDataTypes1_21 ENTITY_DATA_TYPES = new EntityDataTypes1_21(ITEM, PARTICLE, PARTICLES);
|
||||
public static final Type<EntityData> ENTITY_DATA = new EntityDataType(ENTITY_DATA_TYPES);
|
||||
public static final Type<List<EntityData>> ENTITY_DATA_LIST = new EntityDataListType(ENTITY_DATA);
|
||||
}
|
||||
@@ -8,5 +8,5 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
// version must be manually kept in sync with the one in root project settings.gradle.kts
|
||||
implementation("com.github.johnrengelman", "shadow", "8.1.1")
|
||||
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.0")
|
||||
}
|
||||
@@ -5,7 +5,7 @@ plugins {
|
||||
tasks {
|
||||
// Variable replacements
|
||||
processResources {
|
||||
filesMatching(listOf("plugin.yml", "fabric.mod.json")) {
|
||||
filesMatching(listOf("plugin.yml", "META-INF/sponge_plugins.json", "fabric.mod.json")) {
|
||||
expand("version" to project.version, "description" to project.description, "url" to "https://viaversion.com")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import org.gradle.jvm.tasks.Jar
|
||||
plugins {
|
||||
id("via.base-conventions")
|
||||
id("maven-publish")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
||||
@@ -112,7 +112,10 @@ public class JoinListener implements Listener {
|
||||
return;
|
||||
}
|
||||
// The connection has already closed, that was a quick leave
|
||||
if (!channel.isOpen()) return;
|
||||
// Channel may be null if a plugin is manually calling the event for a non-player...
|
||||
if (channel == null || !channel.isOpen()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UserConnection user = getUserConnection(channel);
|
||||
if (user == null) {
|
||||
|
||||
@@ -30,7 +30,7 @@ public class DumpSubCmd implements ViaSubCommand {
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return "Dump information about your server, this is helpful if you report bugs.";
|
||||
return "Dump information about your platform implementation, this is helpful if you report bugs.";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+16
-2
@@ -25,14 +25,14 @@ import com.viaversion.viaversion.api.protocol.version.BlockedProtocolVersions;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.protocol.BlockedProtocolVersionsImpl;
|
||||
import com.viaversion.viaversion.util.Config;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public abstract class AbstractViaConfig extends Config implements ViaVersionConfig {
|
||||
@@ -94,6 +94,8 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
private boolean enforceSecureChat;
|
||||
private boolean handleInvalidItemCount;
|
||||
private boolean cancelBlockSounds;
|
||||
private boolean hideScoreboardNumbers;
|
||||
private boolean fix1_21PlacementRotation;
|
||||
|
||||
protected AbstractViaConfig(final File configFile, final Logger logger) {
|
||||
super(configFile, logger);
|
||||
@@ -161,6 +163,8 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
enforceSecureChat = getBoolean("enforce-secure-chat", false);
|
||||
handleInvalidItemCount = getBoolean("handle-invalid-item-count", false);
|
||||
cancelBlockSounds = getBoolean("cancel-block-sounds", true);
|
||||
hideScoreboardNumbers = getBoolean("hide-scoreboard-numbers", false);
|
||||
fix1_21PlacementRotation = getBoolean("fix-1_21-placement-rotation", false);
|
||||
}
|
||||
|
||||
private BlockedProtocolVersions loadBlockedProtocolVersions() {
|
||||
@@ -542,4 +546,14 @@ public abstract class AbstractViaConfig extends Config implements ViaVersionConf
|
||||
public boolean cancelBlockSounds() {
|
||||
return cancelBlockSounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hideScoreboardNumbers() {
|
||||
return hideScoreboardNumbers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fix1_21PlacementRotation() {
|
||||
return fix1_21PlacementRotation;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.StorableObject;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.entity.EntityTracker;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.platform.ViaInjector;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
@@ -58,6 +59,7 @@ public class UserConnectionImpl implements UserConnection {
|
||||
private final long id = IDS.incrementAndGet();
|
||||
private final Map<Class<?>, StorableObject> storedObjects = new ConcurrentHashMap<>();
|
||||
private final Map<Class<? extends Protocol>, EntityTracker> entityTrackers = new HashMap<>();
|
||||
private final Map<Class<? extends Protocol>, ClientWorld> clientWorlds = new HashMap<>();
|
||||
private final PacketTracker packetTracker = new PacketTracker(this);
|
||||
private final Set<UUID> passthroughTokens = Collections.newSetFromMap(CacheBuilder.newBuilder()
|
||||
.expireAfterWrite(10, TimeUnit.SECONDS)
|
||||
@@ -125,9 +127,17 @@ public class UserConnectionImpl implements UserConnection {
|
||||
|
||||
@Override
|
||||
public void addEntityTracker(Class<? extends Protocol> protocolClass, EntityTracker tracker) {
|
||||
if (!entityTrackers.containsKey(protocolClass)) {
|
||||
entityTrackers.put(protocolClass, tracker);
|
||||
}
|
||||
entityTrackers.putIfAbsent(protocolClass, tracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable <T extends ClientWorld> T getClientWorld(final Class<? extends Protocol> protocolClass) {
|
||||
return (T) clientWorlds.get(protocolClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addClientWorld(final Class<? extends Protocol> protocolClass, final ClientWorld clientWorld) {
|
||||
clientWorlds.putIfAbsent(protocolClass, clientWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -142,7 +152,6 @@ public class UserConnectionImpl implements UserConnection {
|
||||
});
|
||||
for (EntityTracker tracker : entityTrackers.values()) {
|
||||
tracker.clearEntities();
|
||||
tracker.trackClientEntity();
|
||||
}
|
||||
} else {
|
||||
for (StorableObject object : storedObjects.values()) {
|
||||
@@ -150,6 +159,7 @@ public class UserConnectionImpl implements UserConnection {
|
||||
}
|
||||
storedObjects.clear();
|
||||
entityTrackers.clear();
|
||||
clientWorlds.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeListener {
|
||||
private final Int2ObjectMap<TrackedEntity> entities = new Int2ObjectOpenHashMap<>();
|
||||
protected final Int2ObjectMap<TrackedEntity> entities = new Int2ObjectOpenHashMap<>();
|
||||
private final UserConnection connection;
|
||||
private final EntityType playerType;
|
||||
private int clientEntityId = -1;
|
||||
private Integer clientEntityId;
|
||||
private int currentWorldSectionHeight = -1;
|
||||
private int currentMinY;
|
||||
private String currentWorld;
|
||||
@@ -87,7 +87,6 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
return entity != null && entity.hasData() ? entity.data() : null;
|
||||
}
|
||||
|
||||
//TODO Soft memory leak: Remove entities on respawn in protocols prior to 1.18 (1.16+ only when the worldname is different)
|
||||
@Override
|
||||
public void removeEntity(int id) {
|
||||
entities.remove(id);
|
||||
@@ -95,11 +94,27 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
|
||||
@Override
|
||||
public void clearEntities() {
|
||||
entities.clear();
|
||||
// Call wrapper function in case protocols need to do additional removals
|
||||
for (final int id : entities.keySet().toIntArray()) {
|
||||
removeEntity(id);
|
||||
}
|
||||
|
||||
// Re-add the client entity. Keep the call above to untrack attached data if necessary
|
||||
if (clientEntityId != null) {
|
||||
entities.put(clientEntityId.intValue(), new TrackedEntityImpl(playerType));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientEntityId() {
|
||||
public boolean hasClientEntityId() {
|
||||
return clientEntityId != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clientEntityId() throws IllegalStateException {
|
||||
if (clientEntityId == null) {
|
||||
throw new IllegalStateException("Client entity id not set");
|
||||
}
|
||||
return clientEntityId;
|
||||
}
|
||||
|
||||
@@ -107,7 +122,7 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
public void setClientEntityId(int clientEntityId) {
|
||||
Preconditions.checkNotNull(playerType);
|
||||
final TrackedEntity oldEntity;
|
||||
if (this.clientEntityId != -1 && (oldEntity = entities.remove(this.clientEntityId)) != null) {
|
||||
if (this.clientEntityId != null && (oldEntity = entities.remove(this.clientEntityId.intValue())) != null) {
|
||||
entities.put(clientEntityId, oldEntity);
|
||||
} else {
|
||||
entities.put(clientEntityId, new TrackedEntityImpl(playerType));
|
||||
@@ -116,15 +131,6 @@ public class EntityTrackerBase implements EntityTracker, ClientEntityIdChangeLis
|
||||
this.clientEntityId = clientEntityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean trackClientEntity() {
|
||||
if (clientEntityId != -1) {
|
||||
entities.put(clientEntityId, new TrackedEntityImpl(playerType));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int currentWorldSectionHeight() {
|
||||
return currentWorldSectionHeight;
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.viaversion.viaversion.api.protocol.ProtocolManager;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathKey;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.Direction;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
@@ -38,10 +39,9 @@ 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.protocols.base.BaseProtocol;
|
||||
import com.viaversion.viaversion.protocols.base.BaseProtocol1_16;
|
||||
import com.viaversion.viaversion.protocols.base.BaseProtocol1_7;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
|
||||
import com.viaversion.viaversion.protocols.base.InitialBaseProtocol;
|
||||
import com.viaversion.viaversion.protocols.base.v1_7.ClientboundBaseProtocol1_7;
|
||||
import com.viaversion.viaversion.protocols.base.v1_7.ServerboundBaseProtocol1_7;
|
||||
import com.viaversion.viaversion.protocols.v1_10to1_11.Protocol1_10To1_11;
|
||||
import com.viaversion.viaversion.protocols.v1_11_1to1_12.Protocol1_11_1To1_12;
|
||||
import com.viaversion.viaversion.protocols.v1_11to1_11_1.Protocol1_11To1_11_1;
|
||||
@@ -74,7 +74,9 @@ import com.viaversion.viaversion.protocols.v1_19_4to1_20.Protocol1_19_4To1_20;
|
||||
import com.viaversion.viaversion.protocols.v1_19to1_19_1.Protocol1_19To1_19_1;
|
||||
import com.viaversion.viaversion.protocols.v1_20_2to1_20_3.Protocol1_20_2To1_20_3;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.Protocol1_20_3To1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.Protocol1_20_5To1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20to1_20_2.Protocol1_20To1_20_2;
|
||||
import com.viaversion.viaversion.protocols.v1_21to1_21_2.Protocol1_21To1_21_2;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.Protocol1_9_1To1_9_3;
|
||||
import com.viaversion.viaversion.protocols.v1_9_3to1_10.Protocol1_9_3To1_10;
|
||||
@@ -109,14 +111,15 @@ import java.util.logging.Level;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class ProtocolManagerImpl implements ProtocolManager {
|
||||
private static final Protocol BASE_PROTOCOL = new BaseProtocol();
|
||||
private static final Protocol BASE_PROTOCOL = new InitialBaseProtocol();
|
||||
|
||||
// Input Version -> Output Version & Protocol (Allows fast lookup)
|
||||
private final Object2ObjectMap<ProtocolVersion, Object2ObjectMap<ProtocolVersion, Protocol>> registryMap = new Object2ObjectOpenHashMap<>(32);
|
||||
private final Map<Class<? extends Protocol>, Protocol<?, ?, ?, ?>> protocols = new HashMap<>(64);
|
||||
private final Map<ProtocolPathKey, List<ProtocolPathEntry>> pathCache = new ConcurrentHashMap<>();
|
||||
private final Set<ProtocolVersion> supportedVersions = new HashSet<>();
|
||||
private final List<Pair<Range<ProtocolVersion>, Protocol>> baseProtocols = Lists.newCopyOnWriteArrayList();
|
||||
private final List<Pair<Range<ProtocolVersion>, Protocol>> serverboundBaseProtocols = Lists.newCopyOnWriteArrayList();
|
||||
private final List<Pair<Range<ProtocolVersion>, Protocol>> clientboundBaseProtocols = Lists.newCopyOnWriteArrayList();
|
||||
|
||||
private final ReadWriteLock mappingLoaderLock = new ReentrantReadWriteLock();
|
||||
private Map<Class<? extends Protocol>, CompletableFuture<Void>> mappingLoaderFutures = new HashMap<>();
|
||||
@@ -137,8 +140,8 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
// Base Protocol
|
||||
BASE_PROTOCOL.initialize();
|
||||
BASE_PROTOCOL.register(Via.getManager().getProviders());
|
||||
registerBaseProtocol(new BaseProtocol1_7(), Range.closedOpen(ProtocolVersion.v1_7_2, ProtocolVersion.v1_16));
|
||||
registerBaseProtocol(new BaseProtocol1_16(), Range.atLeast(ProtocolVersion.v1_16));
|
||||
registerBaseProtocol(Direction.CLIENTBOUND, new ClientboundBaseProtocol1_7(), Range.atLeast(ProtocolVersion.v1_7_2));
|
||||
registerBaseProtocol(Direction.SERVERBOUND, new ServerboundBaseProtocol1_7(), Range.atLeast(ProtocolVersion.v1_7_2));
|
||||
|
||||
registerProtocol(new Protocol1_8To1_9(), ProtocolVersion.v1_9, ProtocolVersion.v1_8);
|
||||
registerProtocol(new Protocol1_9To1_9_1(), Arrays.asList(ProtocolVersion.v1_9_1, ProtocolVersion.v1_9_2), ProtocolVersion.v1_9);
|
||||
@@ -190,6 +193,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
registerProtocol(new Protocol1_20_3To1_20_5(), ProtocolVersion.v1_20_5, ProtocolVersion.v1_20_3);
|
||||
|
||||
registerProtocol(new Protocol1_20_5To1_21(), ProtocolVersion.v1_21, ProtocolVersion.v1_20_5);
|
||||
registerProtocol(new Protocol1_21To1_21_2(), ProtocolVersion.v1_21_2, ProtocolVersion.v1_21);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -234,7 +238,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBaseProtocol(Protocol baseProtocol, Range<ProtocolVersion> supportedProtocols) {
|
||||
public void registerBaseProtocol(Direction direction, Protocol baseProtocol, Range<ProtocolVersion> supportedProtocols) {
|
||||
Preconditions.checkArgument(baseProtocol.isBaseProtocol(), "Protocol is not a base protocol");
|
||||
final ProtocolVersion lower = supportedProtocols.hasLowerBound() ? supportedProtocols.lowerEndpoint() : null;
|
||||
final ProtocolVersion upper = supportedProtocols.hasUpperBound() ? supportedProtocols.upperEndpoint() : null;
|
||||
@@ -243,7 +247,11 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
|
||||
baseProtocol.initialize();
|
||||
|
||||
baseProtocols.add(new Pair<>(supportedProtocols, baseProtocol));
|
||||
if (direction == Direction.SERVERBOUND) {
|
||||
serverboundBaseProtocols.add(new Pair<>(supportedProtocols, baseProtocol));
|
||||
} else {
|
||||
clientboundBaseProtocols.add(new Pair<>(supportedProtocols, baseProtocol));
|
||||
}
|
||||
baseProtocol.register(Via.getManager().getProviders());
|
||||
if (Via.getManager().isInitialized()) {
|
||||
refreshVersions();
|
||||
@@ -273,12 +281,14 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
ProtocolPathKey protocolKey = new ProtocolPathKeyImpl(clientVersion, serverVersion);
|
||||
List<ProtocolPathEntry> protocolList = pathCache.get(protocolKey);
|
||||
if (protocolList != null) {
|
||||
return protocolList;
|
||||
return protocolList.isEmpty() ? null : protocolList;
|
||||
}
|
||||
|
||||
// Calculate path
|
||||
Object2ObjectSortedMap<ProtocolVersion, Protocol> outputPath = getProtocolPath(new Object2ObjectLinkedOpenHashMap<>(), clientVersion, serverVersion);
|
||||
if (outputPath == null) {
|
||||
// Also cache that there is no path
|
||||
pathCache.put(protocolKey, List.of());
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -365,13 +375,23 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Protocol getBaseProtocol(ProtocolVersion serverVersion) {
|
||||
for (Pair<Range<ProtocolVersion>, Protocol> rangeProtocol : Lists.reverse(baseProtocols)) {
|
||||
if (rangeProtocol.key().contains(serverVersion)) {
|
||||
return rangeProtocol.value();
|
||||
public List<Protocol> getBaseProtocols(@Nullable ProtocolVersion clientVersion, @Nullable ProtocolVersion serverVersion) {
|
||||
final List<Protocol> list = new ArrayList<>();
|
||||
if (clientVersion != null) {
|
||||
for (Pair<Range<ProtocolVersion>, Protocol> rangeProtocol : serverboundBaseProtocols) {
|
||||
if (rangeProtocol.key().contains(clientVersion)) {
|
||||
list.add(rangeProtocol.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
if (serverVersion != null) {
|
||||
for (Pair<Range<ProtocolVersion>, Protocol> rangeProtocol : clientboundBaseProtocols) {
|
||||
if (rangeProtocol.key().contains(serverVersion)) {
|
||||
list.add(rangeProtocol.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -518,7 +538,7 @@ public class ProtocolManagerImpl implements ProtocolManager {
|
||||
Preconditions.checkArgument(!mappingsLoaded);
|
||||
|
||||
// If this log message is missing, something is wrong
|
||||
Via.getPlatform().getLogger().info("Finished mapping loading, shutting down loader executor!");
|
||||
Via.getPlatform().getLogger().info("Finished mapping loading, shutting down loader executor.");
|
||||
mappingsLoaded = true;
|
||||
mappingLoaderExecutor.shutdown();
|
||||
mappingLoaderExecutor = null;
|
||||
|
||||
+11
-2
@@ -24,8 +24,10 @@ import java.util.Comparator;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
/**
|
||||
* Special protocol version that compares to another version. This can be used for e.g. April Fool versions which are depending
|
||||
* on vanilla game versions.
|
||||
* Intended API class for protocol versions with the version type {@link VersionType#SPECIAL}.
|
||||
* <p>
|
||||
* Compares equal to the given origin version and allows base protocol determination via {@link #getBaseProtocolVersion()}
|
||||
* which can be null for special cases where there is no base protocol.
|
||||
*/
|
||||
public class RedirectProtocolVersion extends ProtocolVersion {
|
||||
|
||||
@@ -55,4 +57,11 @@ public class RedirectProtocolVersion extends ProtocolVersion {
|
||||
public ProtocolVersion getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the protocol version used to determine the base protocol, null in case there is no base protocol.
|
||||
*/
|
||||
public @Nullable ProtocolVersion getBaseProtocolVersion() {
|
||||
return origin;
|
||||
}
|
||||
}
|
||||
+60
-19
@@ -123,7 +123,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
continue;
|
||||
}
|
||||
if (currentIndex == index) {
|
||||
packetValue.setValue(attemptTransform(type, value));
|
||||
packetValue.setValue(value);
|
||||
return;
|
||||
}
|
||||
currentIndex++;
|
||||
@@ -133,23 +133,26 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
|
||||
@Override
|
||||
public <T> T read(Type<T> type) {
|
||||
if (readableObjects.isEmpty()) {
|
||||
Preconditions.checkNotNull(inputBuffer, "This packet does not have an input buffer.");
|
||||
// We could in the future log input read values, but honestly for things like bulk maps, mem waste D:
|
||||
try {
|
||||
return type.read(inputBuffer);
|
||||
} catch (Exception e) {
|
||||
throw createInformativeException(e, type, packetValues.size() + 1);
|
||||
}
|
||||
}
|
||||
return readableObjects.isEmpty() ? readFromBuffer(type) : pollReadableObject(type).value;
|
||||
}
|
||||
|
||||
PacketValue readValue = readableObjects.poll();
|
||||
private <T> T readFromBuffer(Type<T> type) {
|
||||
Preconditions.checkNotNull(inputBuffer, "This packet does not have an input buffer.");
|
||||
try {
|
||||
return type.read(inputBuffer);
|
||||
} catch (Exception e) {
|
||||
throw createInformativeException(e, type, packetValues.size() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> PacketValue<T> pollReadableObject(Type<T> type) {
|
||||
PacketValue<?> readValue = readableObjects.poll();
|
||||
Type<?> readType = readValue.type();
|
||||
if (readType == type
|
||||
|| (type.getBaseClass() == readType.getBaseClass()
|
||||
&& type.getOutputClass() == readType.getOutputClass())) {
|
||||
//noinspection unchecked
|
||||
return (T) readValue.value();
|
||||
return (PacketValue<T>) readValue;
|
||||
} else {
|
||||
throw createInformativeException(new IOException("Unable to read type " + type.getTypeName() + ", found " + readValue.type().getTypeName()), type, readableObjects.size());
|
||||
}
|
||||
@@ -157,7 +160,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
|
||||
@Override
|
||||
public <T> void write(Type<T> type, T value) {
|
||||
packetValues.add(new PacketValue<>(type, attemptTransform(type, value)));
|
||||
packetValues.add(new PacketValue<>(type, value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,7 +170,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
* @param value value
|
||||
* @return value if already matching, else the converted value or possibly unmatched value
|
||||
*/
|
||||
private <T> @Nullable T attemptTransform(Type<T> expectedType, @Nullable T value) {
|
||||
private <T> @Nullable T attemptTransform(Type<T> expectedType, @Nullable Object value) {
|
||||
if (value != null && !expectedType.getOutputClass().isAssignableFrom(value.getClass())) {
|
||||
// Attempt conversion
|
||||
if (expectedType instanceof TypeConverter<?>) {
|
||||
@@ -177,14 +180,33 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
|
||||
Via.getPlatform().getLogger().warning("Possible type mismatch: " + value.getClass().getName() + " -> " + expectedType.getOutputClass());
|
||||
}
|
||||
return value;
|
||||
//noinspection unchecked
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T passthrough(Type<T> type) throws InformativeException {
|
||||
T value = read(type);
|
||||
write(type, value);
|
||||
return value;
|
||||
if (readableObjects.isEmpty()) {
|
||||
T value = readFromBuffer(type);
|
||||
packetValues.add(new PacketValue<>(type, value));
|
||||
return value;
|
||||
} else {
|
||||
PacketValue<T> value = pollReadableObject(type);
|
||||
packetValues.add(value);
|
||||
return value.value;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T passthroughAndMap(Type<?> type, Type<T> mappedType) throws InformativeException {
|
||||
if (type == mappedType) {
|
||||
return passthrough(mappedType);
|
||||
}
|
||||
|
||||
final Object value = read(type);
|
||||
final T mappedValue = attemptTransform(mappedType, value);
|
||||
write(mappedType, mappedValue);
|
||||
return mappedValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -318,7 +340,7 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
}
|
||||
return user().sendRawPacketFuture(output);
|
||||
}
|
||||
return user().getChannel().newFailedFuture(new RuntimeException("Tried to send cancelled packet"));
|
||||
return cancelledFuture();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -326,6 +348,21 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
sendRaw(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture sendFutureRaw() throws InformativeException {
|
||||
if (isCancelled()) {
|
||||
return cancelledFuture();
|
||||
}
|
||||
|
||||
ByteBuf output = inputBuffer == null ? user().getChannel().alloc().buffer() : inputBuffer.alloc().buffer();
|
||||
try {
|
||||
writeToBuffer(output);
|
||||
return user().sendRawPacketFuture(output.retain());
|
||||
} finally {
|
||||
output.release();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleSendRaw() throws InformativeException {
|
||||
sendRaw(false);
|
||||
@@ -349,6 +386,10 @@ public class PacketWrapperImpl implements PacketWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
private ChannelFuture cancelledFuture() {
|
||||
return user().getChannel().newFailedFuture(new RuntimeException("Tried to send cancelled packet"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketWrapperImpl create(int packetId) {
|
||||
return new PacketWrapperImpl(packetId, null, user());
|
||||
|
||||
+4
-1
@@ -23,11 +23,14 @@ import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket;
|
||||
public enum ClientboundLoginPackets implements BaseClientboundPacket {
|
||||
LOGIN_DISCONNECT, // 0x00
|
||||
HELLO, // 0x01
|
||||
GAME_PROFILE, // 0x02
|
||||
LOGIN_FINISHED, // 0x02
|
||||
LOGIN_COMPRESSION, // 0x03
|
||||
CUSTOM_QUERY, // 0x04
|
||||
COOKIE_REQUEST; // 0x05
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public static final ClientboundLoginPackets GAME_PROFILE = LOGIN_FINISHED;
|
||||
|
||||
@Override
|
||||
public final int getId() {
|
||||
return ordinal();
|
||||
|
||||
+34
-11
@@ -35,6 +35,7 @@ import com.viaversion.viaversion.api.protocol.version.VersionType;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.exception.CancelException;
|
||||
import com.viaversion.viaversion.exception.InformativeException;
|
||||
import com.viaversion.viaversion.protocol.RedirectProtocolVersion;
|
||||
import com.viaversion.viaversion.protocol.version.BaseVersionProvider;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BasePacketTypesProvider;
|
||||
@@ -42,19 +43,24 @@ import com.viaversion.viaversion.protocols.base.packet.BaseServerboundPacket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BaseProtocol extends AbstractProtocol<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> {
|
||||
/**
|
||||
* Initial base protocol which is kept always in the pipeline.
|
||||
* <p>
|
||||
* State tracking for configuration state is done via {@link AbstractProtocol#registerConfigurationChangeHandlers()}
|
||||
*/
|
||||
public class InitialBaseProtocol extends AbstractProtocol<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> {
|
||||
|
||||
private static final int STATUS_INTENT = 1;
|
||||
private static final int LOGIN_INTENT = 2;
|
||||
private static final int TRANSFER_INTENT = 3;
|
||||
|
||||
public BaseProtocol() {
|
||||
public InitialBaseProtocol() {
|
||||
super(BaseClientboundPacket.class, BaseClientboundPacket.class, BaseServerboundPacket.class, BaseServerboundPacket.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
// Handshake Packet
|
||||
// Setup protocol pipeline + track initial state
|
||||
registerServerbound(ServerboundHandshakePackets.CLIENT_INTENTION, wrapper -> {
|
||||
int protocolVersion = wrapper.passthrough(Types.VAR_INT);
|
||||
wrapper.passthrough(Types.STRING); // Server Address
|
||||
@@ -89,16 +95,22 @@ public class BaseProtocol extends AbstractProtocol<BaseClientboundPacket, BaseCl
|
||||
ProtocolManager protocolManager = Via.getManager().getProtocolManager();
|
||||
List<ProtocolPathEntry> protocolPath = protocolManager.getProtocolPath(info.protocolVersion(), serverProtocol);
|
||||
|
||||
// Add Base Protocol
|
||||
ProtocolPipeline pipeline = info.getPipeline();
|
||||
|
||||
// Special versions might compare equal to normal versions and would break this getter
|
||||
// Save manually added protocols for later
|
||||
List<Protocol> alreadyAdded = new ArrayList<>(pipeline.pipes());
|
||||
|
||||
// Special versions might compare equal to normal versions and would the normal lookup,
|
||||
// platforms can use the RedirectProtocolVersion API or need to manually handle their base protocols.
|
||||
ProtocolVersion clientboundBaseProtocolVersion = null;
|
||||
if (serverProtocol.getVersionType() != VersionType.SPECIAL) {
|
||||
final Protocol baseProtocol = protocolManager.getBaseProtocol(serverProtocol);
|
||||
// Platforms might add their base protocol manually (e.g. SPECIAL versions)
|
||||
if (baseProtocol != null) {
|
||||
pipeline.add(baseProtocol);
|
||||
}
|
||||
clientboundBaseProtocolVersion = serverProtocol;
|
||||
} else if (serverProtocol instanceof RedirectProtocolVersion version) {
|
||||
clientboundBaseProtocolVersion = version.getBaseProtocolVersion();
|
||||
}
|
||||
// Add base protocols
|
||||
for (final Protocol protocol : protocolManager.getBaseProtocols(info.protocolVersion(), clientboundBaseProtocolVersion)) {
|
||||
pipeline.add(protocol);
|
||||
}
|
||||
|
||||
// Add other protocols
|
||||
@@ -118,11 +130,22 @@ public class BaseProtocol extends AbstractProtocol<BaseClientboundPacket, BaseCl
|
||||
wrapper.set(Types.VAR_INT, 0, serverProtocol.getOriginalVersion());
|
||||
}
|
||||
|
||||
// Send client intention into the pipeline in case protocols down the line need to transform it
|
||||
try {
|
||||
final List<Protocol> protocols = new ArrayList<>(pipeline.pipes());
|
||||
protocols.removeAll(alreadyAdded); // Skip all manually added protocols to prevent double handling
|
||||
wrapper.resetReader();
|
||||
wrapper.apply(Direction.SERVERBOUND, State.HANDSHAKE, protocols);
|
||||
} catch (CancelException e) {
|
||||
wrapper.cancel();
|
||||
}
|
||||
|
||||
if (Via.getManager().isDebug()) {
|
||||
Via.getPlatform().getLogger().info("User connected with protocol: " + info.protocolVersion() + " and serverProtocol: " + info.serverProtocolVersion());
|
||||
Via.getPlatform().getLogger().info("Protocol pipeline: " + pipeline.pipes());
|
||||
}
|
||||
|
||||
// Set initial state
|
||||
if (state == STATUS_INTENT) {
|
||||
info.setState(State.STATUS);
|
||||
} else if (state == LOGIN_INTENT) {
|
||||
@@ -162,4 +185,4 @@ public class BaseProtocol extends AbstractProtocol<BaseClientboundPacket, BaseCl
|
||||
protected PacketTypesProvider<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> createPacketTypesProvider() {
|
||||
return BasePacketTypesProvider.INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
-66
@@ -15,7 +15,7 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.base;
|
||||
package com.viaversion.viaversion.protocols.base.v1_7;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -26,7 +26,6 @@ import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.ProtocolPathEntry;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
@@ -35,25 +34,25 @@ import com.viaversion.viaversion.api.protocol.version.VersionProvider;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocol.ProtocolManagerImpl;
|
||||
import com.viaversion.viaversion.protocol.ServerProtocolVersionSingleton;
|
||||
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
|
||||
import com.viaversion.viaversion.protocols.base.ClientboundStatusPackets;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BasePacketTypesProvider;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BaseServerboundPacket;
|
||||
import com.viaversion.viaversion.util.ChatColorUtil;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import com.viaversion.viaversion.util.GsonUtil;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class BaseProtocol1_7 extends AbstractProtocol<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> {
|
||||
public class ClientboundBaseProtocol1_7 extends AbstractProtocol<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> {
|
||||
|
||||
public BaseProtocol1_7() {
|
||||
public ClientboundBaseProtocol1_7() {
|
||||
super(BaseClientboundPacket.class, BaseClientboundPacket.class, BaseServerboundPacket.class, BaseServerboundPacket.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
// Handle server pinging sent by the client
|
||||
registerClientbound(ClientboundStatusPackets.STATUS_RESPONSE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
@@ -128,60 +127,27 @@ public class BaseProtocol1_7 extends AbstractProtocol<BaseClientboundPacket, Bas
|
||||
}
|
||||
});
|
||||
|
||||
// Login Success Packet
|
||||
registerClientbound(ClientboundLoginPackets.GAME_PROFILE, wrapper -> {
|
||||
ProtocolInfo info = wrapper.user().getProtocolInfo();
|
||||
if (info.protocolVersion().olderThan(ProtocolVersion.v1_20_2)) { // On 1.20.2+, wait for the login ack
|
||||
info.setState(State.PLAY);
|
||||
}
|
||||
|
||||
UUID uuid = passthroughLoginUUID(wrapper);
|
||||
info.setUuid(uuid);
|
||||
|
||||
String username = wrapper.passthrough(Types.STRING);
|
||||
info.setUsername(username);
|
||||
// Add to ported clients
|
||||
Via.getManager().getConnectionManager().onLoginSuccess(wrapper.user());
|
||||
|
||||
if (!info.getPipeline().hasNonBaseProtocols()) { // Only base protocol
|
||||
wrapper.user().setActive(false);
|
||||
}
|
||||
|
||||
if (Via.getManager().isDebug()) {
|
||||
// Print out the route to console
|
||||
Via.getPlatform().getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}",
|
||||
new Object[]{
|
||||
username,
|
||||
info.protocolVersion().getName(),
|
||||
Joiner.on(", ").join(info.getPipeline().pipes(), ", ")
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Login Start Packet
|
||||
registerServerbound(ServerboundLoginPackets.HELLO, wrapper -> {
|
||||
final UserConnection user = wrapper.user();
|
||||
final ProtocolVersion protocol = user.getProtocolInfo().protocolVersion();
|
||||
if (Via.getConfig().blockedProtocolVersions().contains(protocol)) {
|
||||
if (!user.getChannel().isOpen() || !user.shouldApplyBlockProtocol()) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.cancel(); // cancel current
|
||||
|
||||
final String disconnectMessage = ChatColorUtil.translateAlternateColorCodes(Via.getConfig().getBlockedDisconnectMsg());
|
||||
final PacketWrapper disconnectPacket = PacketWrapper.create(ClientboundLoginPackets.LOGIN_DISCONNECT, user);
|
||||
disconnectPacket.write(Types.COMPONENT, ComponentUtil.plainToJson(disconnectMessage));
|
||||
|
||||
// Send and close
|
||||
final ChannelFuture future = disconnectPacket.sendFuture(null);
|
||||
future.addListener(f -> user.getChannel().close());
|
||||
}
|
||||
});
|
||||
|
||||
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> {
|
||||
// Track player name/uuid and setup connection + track state
|
||||
registerClientbound(ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
|
||||
final ProtocolInfo info = wrapper.user().getProtocolInfo();
|
||||
info.setState(State.CONFIGURATION);
|
||||
|
||||
if (info.serverProtocolVersion().olderThan(ProtocolVersion.v1_16)) {
|
||||
String uuidString = wrapper.passthrough(Types.STRING);
|
||||
if (uuidString.length() == 32) { // Trimmed UUIDs are 32 characters
|
||||
// Trimmed
|
||||
uuidString = addDashes(uuidString);
|
||||
}
|
||||
info.setUuid(UUID.fromString(uuidString));
|
||||
} else {
|
||||
final UUID uuid = wrapper.passthrough(Types.UUID);
|
||||
info.setUuid(uuid);
|
||||
}
|
||||
|
||||
final String username = wrapper.passthrough(Types.STRING);
|
||||
info.setUsername(username);
|
||||
|
||||
// Setup connection
|
||||
onLoginSuccess(wrapper.user());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -199,13 +165,28 @@ public class BaseProtocol1_7 extends AbstractProtocol<BaseClientboundPacket, Bas
|
||||
return idBuff.toString();
|
||||
}
|
||||
|
||||
protected UUID passthroughLoginUUID(PacketWrapper wrapper) {
|
||||
String uuidString = wrapper.passthrough(Types.STRING);
|
||||
if (uuidString.length() == 32) { // Trimmed UUIDs are 32 characters
|
||||
// Trimmed
|
||||
uuidString = addDashes(uuidString);
|
||||
public static void onLoginSuccess(final UserConnection connection) {
|
||||
final ProtocolInfo info = connection.getProtocolInfo();
|
||||
if (info.protocolVersion().olderThan(ProtocolVersion.v1_20_2)) { // On 1.20.2+, wait for the login ack
|
||||
info.setState(State.PLAY);
|
||||
}
|
||||
|
||||
// Add to ported clients
|
||||
Via.getManager().getConnectionManager().onLoginSuccess(connection);
|
||||
|
||||
if (!info.getPipeline().hasNonBaseProtocols()) { // Only base protocol
|
||||
connection.setActive(false);
|
||||
}
|
||||
|
||||
if (Via.getManager().isDebug()) {
|
||||
// Print out the route to console
|
||||
Via.getPlatform().getLogger().log(Level.INFO, "{0} logged in with protocol {1}, Route: {2}",
|
||||
new Object[]{
|
||||
info.getUsername(),
|
||||
info.protocolVersion().getName(),
|
||||
Joiner.on(", ").join(info.getPipeline().pipes(), ", ")
|
||||
});
|
||||
}
|
||||
return UUID.fromString(uuidString);
|
||||
}
|
||||
|
||||
@Override
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.base.v1_7;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.connection.ProtocolInfo;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.protocols.base.ClientboundLoginPackets;
|
||||
import com.viaversion.viaversion.protocols.base.ServerboundLoginPackets;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BaseClientboundPacket;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BasePacketTypesProvider;
|
||||
import com.viaversion.viaversion.protocols.base.packet.BaseServerboundPacket;
|
||||
import com.viaversion.viaversion.protocols.v1_8to1_9.Protocol1_8To1_9;
|
||||
import com.viaversion.viaversion.util.ChatColorUtil;
|
||||
import com.viaversion.viaversion.util.ComponentUtil;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
|
||||
public class ServerboundBaseProtocol1_7 extends AbstractProtocol<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> {
|
||||
|
||||
public ServerboundBaseProtocol1_7() {
|
||||
super(BaseClientboundPacket.class, BaseClientboundPacket.class, BaseServerboundPacket.class, BaseServerboundPacket.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
// State tracking
|
||||
registerServerbound(ServerboundLoginPackets.LOGIN_ACKNOWLEDGED, wrapper -> {
|
||||
final ProtocolInfo info = wrapper.user().getProtocolInfo();
|
||||
info.setState(State.CONFIGURATION);
|
||||
});
|
||||
|
||||
// Handle blocked version disconnect
|
||||
registerServerbound(ServerboundLoginPackets.HELLO, wrapper -> {
|
||||
final UserConnection user = wrapper.user();
|
||||
final ProtocolVersion protocol = user.getProtocolInfo().protocolVersion();
|
||||
if (Via.getConfig().blockedProtocolVersions().contains(protocol)) {
|
||||
if (!user.getChannel().isOpen() || !user.shouldApplyBlockProtocol()) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.cancel(); // cancel current
|
||||
|
||||
final String disconnectMessage = ChatColorUtil.translateAlternateColorCodes(Via.getConfig().getBlockedDisconnectMsg());
|
||||
final PacketWrapper disconnectPacket = PacketWrapper.create(ClientboundLoginPackets.LOGIN_DISCONNECT, user);
|
||||
|
||||
final JsonObject object = ComponentUtil.plainToJson(disconnectMessage);
|
||||
if (protocol.olderThanOrEqualTo(ProtocolVersion.v1_8)) {
|
||||
disconnectPacket.write(Types.STRING, object.toString());
|
||||
} else {
|
||||
disconnectPacket.write(Types.COMPONENT, object);
|
||||
}
|
||||
|
||||
// Send and close
|
||||
final ChannelFuture future = disconnectPacket.sendFutureRaw();
|
||||
future.addListener(f -> user.getChannel().close());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBaseProtocol() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PacketTypesProvider<BaseClientboundPacket, BaseClientboundPacket, BaseServerboundPacket, BaseServerboundPacket> createPacketTypesProvider() {
|
||||
return BasePacketTypesProvider.INSTANCE;
|
||||
}
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_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.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.rewriter.RecipeDisplayRewriter;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
|
||||
// To replace if needed:
|
||||
// ChunkType1_20_2
|
||||
// RecipeRewriter1_20_3
|
||||
// Types1_21, Types1_OLD
|
||||
final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_21, ServerboundPacket1_20_5, Protocol1_99To_98> {
|
||||
|
||||
public BlockItemPacketRewriter1_99(final Protocol1_99To_98 protocol) {
|
||||
super(protocol, Types1_21.ITEM, Types1_21.ITEM_ARRAY);
|
||||
/*super(protocol,
|
||||
Types1_OLD.ITEM, Types1_OLD.ITEM_ARRAY, Types1_21.ITEM, Types1_21.ITEM_ARRAY,
|
||||
Types1_OLD.ITEM_COST, Types1_OLD.OPTIONAL_ITEM_COST, Types1_21.ITEM_COST, Types1_21.OPTIONAL_ITEM_COST,
|
||||
Types1_OLD.PARTICLE, Types1_21.PARTICLE
|
||||
);*/
|
||||
}
|
||||
|
||||
@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<ClientboundPacket1_21> blockRewriter = BlockRewriter.for1_20_2(protocol);
|
||||
blockRewriter.registerBlockEvent(ClientboundPackets1_21.BLOCK_EVENT);
|
||||
blockRewriter.registerBlockUpdate(ClientboundPackets1_21.BLOCK_UPDATE);
|
||||
blockRewriter.registerSectionBlocksUpdate1_20(ClientboundPackets1_21.SECTION_BLOCKS_UPDATE);
|
||||
blockRewriter.registerLevelEvent1_21(ClientboundPackets1_21.LEVEL_EVENT, 2001);
|
||||
blockRewriter.registerLevelChunk1_19(ClientboundPackets1_21.LEVEL_CHUNK_WITH_LIGHT, ChunkType1_20_2::new);
|
||||
blockRewriter.registerBlockEntityData(ClientboundPackets1_21.BLOCK_ENTITY_DATA);
|
||||
|
||||
// Registers item id changes
|
||||
// Other places using item ids are: Entity data, tags, statistics, effect
|
||||
// registerOpenScreen(ClientboundPackets1_21.OPEN_SCREEN); If a new container type was added; also remove from the component rewriter registration
|
||||
//protocol.registerClientbound(ClientboundPackets1_21_2.SET_CURSOR_ITEM, this::passthroughClientboundItem);
|
||||
registerCooldown1_21_2(ClientboundPackets1_21.COOLDOWN);
|
||||
registerSetContent1_21_2(ClientboundPackets1_21.CONTAINER_SET_CONTENT);
|
||||
registerSetSlot1_21_2(ClientboundPackets1_21.CONTAINER_SET_SLOT);
|
||||
registerAdvancements1_20_3(ClientboundPackets1_21.UPDATE_ADVANCEMENTS);
|
||||
registerSetEquipment(ClientboundPackets1_21.SET_EQUIPMENT);
|
||||
registerContainerClick1_21_2(ServerboundPackets1_20_5.CONTAINER_CLICK);
|
||||
registerMerchantOffers1_20_5(ClientboundPackets1_21.MERCHANT_OFFERS);
|
||||
registerSetCreativeModeSlot(ServerboundPackets1_20_5.SET_CREATIVE_MODE_SLOT);
|
||||
registerLevelParticles1_20_5(ClientboundPackets1_21.LEVEL_PARTICLES);
|
||||
registerExplosion1_21_2(ClientboundPackets1_21.EXPLODE); // Rewrites the included sound and particles
|
||||
|
||||
final RecipeDisplayRewriter<ClientboundPacket1_21> recipeRewriter = new RecipeDisplayRewriter<>(protocol);
|
||||
recipeRewriter.registerUpdateRecipes(ClientboundPackets1_21.UPDATE_RECIPES);
|
||||
//recipeRewriter.registerRecipeBookAdd(ClientboundPackets1_21.RECIPE_BOOK_ADD);
|
||||
recipeRewriter.registerPlaceGhostRecipe(ClientboundPackets1_21.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
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of ViaVersion - https://github.com/ViaVersion/ViaVersion
|
||||
* Copyright (C) 2016-2024 ViaVersion and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.util.SerializerVersion;
|
||||
|
||||
public final class ComponentRewriter1_99 extends ComponentRewriter<ClientboundPacket1_21> {
|
||||
|
||||
public ComponentRewriter1_99(final Protocol1_99To_98 protocol) {
|
||||
super(protocol, ReadType.NBT);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleShowItem(final UserConnection connection, final CompoundTag itemTag, final CompoundTag componentsTag) {
|
||||
super.handleShowItem(connection, itemTag, componentsTag);
|
||||
if (componentsTag == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove or update data from componentsTag
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SerializerVersion inputSerializerVersion() {
|
||||
return SerializerVersion.V1_20_5;
|
||||
}
|
||||
}
|
||||
+23
-25
@@ -15,25 +15,24 @@
|
||||
* 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.template.protocols.rewriter;
|
||||
package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.RegistryEntry;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
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.ClientboundPacket1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
import com.viaversion.viaversion.template.protocols.Protocol1_99To_98;
|
||||
import com.viaversion.viaversion.util.Key;
|
||||
|
||||
// Replace if needed
|
||||
// Types1_OLD
|
||||
// Types1_20_5
|
||||
public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_20_5, Protocol1_99To_98> {
|
||||
// Types1_21
|
||||
final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPacket1_21, Protocol1_99To_98> {
|
||||
|
||||
public EntityPacketRewriter1_99(final Protocol1_99To_98 protocol) {
|
||||
super(protocol);
|
||||
@@ -42,17 +41,17 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
|
||||
@Override
|
||||
public void registerPackets() {
|
||||
// Tracks entities, applies entity data rewrites registered below, untracks entities
|
||||
registerTrackerWithData1_19(ClientboundPackets1_20_5.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets1_20_5.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_20_5.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
|
||||
registerRemoveEntities(ClientboundPackets1_20_5.REMOVE_ENTITIES);
|
||||
registerTrackerWithData1_19(ClientboundPackets1_21.ADD_ENTITY, EntityTypes1_20_5.FALLING_BLOCK);
|
||||
registerSetEntityData(ClientboundPackets1_21.SET_ENTITY_DATA, /*Types1_OLD_ENTITY_DATA_LIST, */Types1_21.ENTITY_DATA_LIST); // Specify old and new entity data list if changed
|
||||
registerRemoveEntities(ClientboundPackets1_21.REMOVE_ENTITIES);
|
||||
|
||||
protocol.registerClientbound(ClientboundConfigurationPackets1_20_5.REGISTRY_DATA, wrapper -> {
|
||||
protocol.registerClientbound(ClientboundConfigurationPackets1_21.REGISTRY_DATA, wrapper -> {
|
||||
final String registryKey = Key.stripMinecraftNamespace(wrapper.passthrough(Types.STRING));
|
||||
final RegistryEntry[] entries = wrapper.passthrough(Types.REGISTRY_ENTRY_ARRAY);
|
||||
handleRegistryData1_20_5(wrapper.user(), registryKey, entries); // Caches dimensions to access data like height later and tracks the amount of biomes sent for chunk data
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_20_5.LOGIN, new PacketHandlers() {
|
||||
protocol.registerClientbound(ClientboundPackets1_21.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // Entity id
|
||||
@@ -71,7 +70,7 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_20_5.RESPAWN, wrapper -> {
|
||||
protocol.registerClientbound(ClientboundPackets1_21.RESPAWN, wrapper -> {
|
||||
final int dimensionId = wrapper.passthrough(Types.VAR_INT);
|
||||
final String world = wrapper.passthrough(Types.STRING);
|
||||
trackWorldDataByKey1_20_5(wrapper.user(), dimensionId, world); // Tracks world height and name for chunk data and entity (un)tracking
|
||||
@@ -82,24 +81,23 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
|
||||
protected void registerRewrites() {
|
||||
/* Uncomment if entity data classes changed
|
||||
filter().mapDataType(typeId -> {
|
||||
final int id = typeId;
|
||||
int id = typeId;
|
||||
if (id >= SomeAddedIndex) {
|
||||
id++;
|
||||
}
|
||||
return Types1_20_5.ENTITY_DATA_TYPES.byId(id);
|
||||
return Types1_21.ENTITY_DATA_TYPES.byId(id);
|
||||
});*/
|
||||
|
||||
// Registers registry type id changes
|
||||
registerEntityDataTypeHandler(
|
||||
Types1_20_5.ENTITY_DATA_TYPES.itemType,
|
||||
Types1_20_5.ENTITY_DATA_TYPES.blockStateType,
|
||||
Types1_20_5.ENTITY_DATA_TYPES.optionalBlockStateType,
|
||||
Types1_20_5.ENTITY_DATA_TYPES.particleType,
|
||||
Types1_20_5.ENTITY_DATA_TYPES.particlesType,
|
||||
Types1_20_5.ENTITY_DATA_TYPES.componentType,
|
||||
Types1_20_5.ENTITY_DATA_TYPES.optionalComponentType
|
||||
Types1_21.ENTITY_DATA_TYPES.itemType,
|
||||
Types1_21.ENTITY_DATA_TYPES.blockStateType,
|
||||
Types1_21.ENTITY_DATA_TYPES.optionalBlockStateType,
|
||||
Types1_21.ENTITY_DATA_TYPES.particleType,
|
||||
Types1_21.ENTITY_DATA_TYPES.particlesType,
|
||||
Types1_21.ENTITY_DATA_TYPES.componentType,
|
||||
Types1_21.ENTITY_DATA_TYPES.optionalComponentType
|
||||
);
|
||||
// Minecarts are special
|
||||
registerBlockStateHandler(EntityTypes1_20_5.ABSTRACT_MINECART, 11);
|
||||
}
|
||||
|
||||
@@ -113,4 +111,4 @@ public final class EntityPacketRewriter1_99 extends EntityRewriter<ClientboundPa
|
||||
public EntityType typeFromId(final int type) {
|
||||
return EntityTypes1_20_5.getTypeFromId(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
+59
-37
@@ -15,7 +15,7 @@
|
||||
* 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.template.protocols;
|
||||
package com.viaversion.viaversion.protocols.template;
|
||||
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
@@ -24,66 +24,80 @@ import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
|
||||
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.rewriter.ComponentRewriter;
|
||||
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
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.ClientboundPacket1_20_5;
|
||||
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.ServerboundConfigurationPackets1_20_5;
|
||||
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPacket1_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.ClientboundConfigurationPackets1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPacket1_21;
|
||||
import com.viaversion.viaversion.protocols.v1_20_5to1_21.packet.ClientboundPackets1_21;
|
||||
import com.viaversion.viaversion.rewriter.AttributeRewriter;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
|
||||
import com.viaversion.viaversion.rewriter.TagRewriter;
|
||||
import com.viaversion.viaversion.template.protocols.rewriter.BlockItemPacketRewriter1_99;
|
||||
import com.viaversion.viaversion.template.protocols.rewriter.EntityPacketRewriter1_99;
|
||||
|
||||
import static com.viaversion.viaversion.util.ProtocolUtil.packetTypeMap;
|
||||
|
||||
// Placeholders to replace (in the entire package):
|
||||
// Protocol1_99To_98, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99
|
||||
// ClientboundPacket1_20_5
|
||||
// Protocol1_99To_98, EntityPacketRewriter1_99, BlockItemPacketRewriter1_99 - move the latter two to a rewriter package
|
||||
// ClientboundPacket1_21
|
||||
// ServerboundPacket1_20_5
|
||||
// EntityTypes1_20_5 (MAPPED type)
|
||||
// 1.99, 1.98
|
||||
public final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_20_5, ClientboundPacket1_20_5, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
|
||||
final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> {
|
||||
|
||||
public static final MappingData MAPPINGS = new MappingDataBase("1.98", "1.99");
|
||||
private final EntityPacketRewriter1_99 entityRewriter = new EntityPacketRewriter1_99(this);
|
||||
private final BlockItemPacketRewriter1_99 itemRewriter = new BlockItemPacketRewriter1_99(this);
|
||||
private final TagRewriter<ClientboundPacket1_20_5> tagRewriter = new TagRewriter<>(this);
|
||||
private final TagRewriter<ClientboundPacket1_21> tagRewriter = new TagRewriter<>(this);
|
||||
private final ComponentRewriter1_99 componentRewriter = new ComponentRewriter1_99(this);
|
||||
|
||||
public Protocol1_99To_98() {
|
||||
// Passing the class types into the super constructor is needed for automatic packet type id remapping, but can otherwise be omitted
|
||||
super(ClientboundPacket1_20_5.class, ClientboundPacket1_20_5.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
|
||||
super(ClientboundPacket1_21.class, ClientboundPacket1_21.class, ServerboundPacket1_20_5.class, ServerboundPacket1_20_5.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
super.registerPackets();
|
||||
|
||||
tagRewriter.registerGeneric(ClientboundPackets1_20_5.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_20_5.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundPackets1_21.UPDATE_TAGS);
|
||||
tagRewriter.registerGeneric(ClientboundConfigurationPackets1_21.UPDATE_TAGS);
|
||||
|
||||
final SoundRewriter<ClientboundPacket1_20_5> soundRewriter = new SoundRewriter<>(this);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_20_5.SOUND_ENTITY);
|
||||
// If needed for item or component changes
|
||||
componentRewriter.registerOpenScreen(ClientboundPackets1_21.OPEN_SCREEN);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SET_ACTION_BAR_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SET_TITLE_TEXT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SET_SUBTITLE_TEXT);
|
||||
componentRewriter.registerBossEvent(ClientboundPackets1_21.BOSS_EVENT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.DISCONNECT);
|
||||
componentRewriter.registerTabList(ClientboundPackets1_21.TAB_LIST);
|
||||
componentRewriter.registerPlayerCombatKill1_20(ClientboundPackets1_21.PLAYER_COMBAT_KILL);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.SYSTEM_CHAT);
|
||||
componentRewriter.registerComponentPacket(ClientboundPackets1_21.DISGUISED_CHAT);
|
||||
componentRewriter.registerPlayerInfoUpdate1_21_2(ClientboundPackets1_21.PLAYER_INFO_UPDATE);
|
||||
componentRewriter.registerPing();
|
||||
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets1_20_5.AWARD_STATS);
|
||||
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_20_5.UPDATE_ATTRIBUTES);
|
||||
final SoundRewriter<ClientboundPacket1_21> soundRewriter = new SoundRewriter<>(this);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND);
|
||||
soundRewriter.registerSound1_19_3(ClientboundPackets1_21.SOUND_ENTITY);
|
||||
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets1_21.AWARD_STATS);
|
||||
new AttributeRewriter<>(this).register1_21(ClientboundPackets1_21.UPDATE_ATTRIBUTES);
|
||||
|
||||
// Uncomment if an existing type changed serialization format. Mappings for argument type keys can also be defined in mapping files
|
||||
/*final CommandRewriter1_19_4<ClientboundPackets1_20_5> commandRewriter = new CommandRewriter1_19_4<ClientboundPackets1_20_5>(this) {
|
||||
/*new CommandRewriter1_19_4<>(this) {
|
||||
@Override
|
||||
public void handleArgument(final PacketWrapper wrapper, final String argumentType) throws Exception {
|
||||
public void handleArgument(final PacketWrapper wrapper, final String argumentType) {
|
||||
if (argumentType.equals("minecraft:abc")) {
|
||||
// New argument
|
||||
wrapper.write(Type.INT, 0);
|
||||
wrapper.write(Types.INT, 0);
|
||||
} else {
|
||||
super.handleArgument(wrapper, argumentType);
|
||||
}
|
||||
}
|
||||
}.registerDeclareCommands1_19(ClientboundPackets1_20_5.DECLARE_COMMANDS);*/
|
||||
}.registerDeclareCommands1_19(ClientboundPackets1_21.COMMANDS);*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,16 +106,19 @@ public final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1
|
||||
// EntityTypes1_20_5.initialize(this);
|
||||
|
||||
// Uncomment if a new particle was added = ids shifted; requires a new Types_ class copied from the last
|
||||
/*Types1_20_5.PARTICLE.filler(this)
|
||||
.reader("block", ParticleType.Readers.BLOCK)
|
||||
.reader("block_marker", ParticleType.Readers.BLOCK)
|
||||
.reader("dust", ParticleType.Readers.DUST)
|
||||
.reader("falling_dust", ParticleType.Readers.BLOCK)
|
||||
.reader("dust_color_transition", ParticleType.Readers.DUST_TRANSITION)
|
||||
.reader("item", ParticleType.Readers.ITEM1_20_2)
|
||||
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
|
||||
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
|
||||
.reader("shriek", ParticleType.Readers.SHRIEK);*/
|
||||
/*Types1_21_2.PARTICLE.filler(this)
|
||||
.reader("block", ParticleType.Readers.BLOCK)
|
||||
.reader("block_marker", ParticleType.Readers.BLOCK)
|
||||
.reader("dust", ParticleType.Readers.DUST1_21_2)
|
||||
.reader("dust_pillar", ParticleType.Readers.BLOCK)
|
||||
.reader("falling_dust", ParticleType.Readers.BLOCK)
|
||||
.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("trail", ParticleType.Readers.TRAIL)
|
||||
.reader("item", ParticleType.Readers.item(itemRewriter.mappedItemType()));*/
|
||||
|
||||
super.onMappingDataLoaded(); // Calls load methods on rewriters. Last in case the rewriters access the above filled data
|
||||
}
|
||||
@@ -130,17 +147,22 @@ public final class Protocol1_99To_98 extends AbstractProtocol<ClientboundPacket1
|
||||
}
|
||||
|
||||
@Override
|
||||
public TagRewriter<ClientboundPacket1_20_5> getTagRewriter() {
|
||||
public TagRewriter<ClientboundPacket1_21> getTagRewriter() {
|
||||
return tagRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PacketTypesProvider<ClientboundPacket1_20_5, ClientboundPacket1_20_5, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
|
||||
public ComponentRewriter getComponentRewriter() {
|
||||
return componentRewriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PacketTypesProvider<ClientboundPacket1_21, ClientboundPacket1_21, ServerboundPacket1_20_5, ServerboundPacket1_20_5> createPacketTypesProvider() {
|
||||
return new SimplePacketTypesProvider<>(
|
||||
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
|
||||
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_20_5.class, ClientboundConfigurationPackets1_20_5.class),
|
||||
packetTypeMap(unmappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedClientboundPacketType, ClientboundPackets1_21.class, ClientboundConfigurationPackets1_21.class),
|
||||
packetTypeMap(mappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class),
|
||||
packetTypeMap(unmappedServerboundPacketType, ServerboundPackets1_20_5.class, ServerboundConfigurationPackets1_20_5.class)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-30
@@ -99,7 +99,7 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_11.class);
|
||||
|
||||
Chunk chunk = wrapper.passthrough(ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment()));
|
||||
|
||||
@@ -120,31 +120,6 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
|
||||
}
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_9_3.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Entity ID
|
||||
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
|
||||
map(Types.INT); // 2 - Dimension
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientChunks.setEnvironment(dimensionId);
|
||||
});
|
||||
}
|
||||
});
|
||||
registerClientbound(ClientboundPackets1_9_3.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT);
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.registerClientbound(ClientboundPackets1_9_3.LEVEL_EVENT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
@@ -238,11 +213,8 @@ public class Protocol1_10To1_11 extends AbstractProtocol<ClientboundPackets1_9_3
|
||||
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
// Entity tracker
|
||||
userConnection.addEntityTracker(this.getClass(), new EntityTracker1_11(userConnection));
|
||||
|
||||
if (!userConnection.has(ClientWorld.class))
|
||||
userConnection.put(new ClientWorld());
|
||||
userConnection.addClientWorld(this.getClass(), new ClientWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
public class PotionColorMappings1_11 {
|
||||
|
||||
//<oldData> to <newData, isInstant> mapping
|
||||
private static final Int2ObjectMap<Pair<Integer, Boolean>> POTIONS = new Int2ObjectOpenHashMap<>(37, 0.99F);
|
||||
private static final Int2ObjectMap<Pair<Integer, Boolean>> POTIONS = new Int2ObjectOpenHashMap<>(37);
|
||||
|
||||
static {
|
||||
addRewrite(0, 3694022, false);
|
||||
|
||||
+29
@@ -20,6 +20,7 @@ package com.viaversion.viaversion.protocols.v1_10to1_11.rewriter;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.StringTag;
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_10;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_11.EntityType;
|
||||
@@ -48,6 +49,34 @@ public class EntityPacketRewriter1_11 extends EntityRewriter<ClientboundPackets1
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_9_3.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Entity ID
|
||||
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
|
||||
map(Types.INT); // 2 - Dimension
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_11.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9_3.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT);
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_10To1_11.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
if (clientWorld.setEnvironment(dimensionId)) {
|
||||
tracker(wrapper.user()).clearEntities();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9_3.ADD_ENTITY, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
|
||||
+28
-5
@@ -19,6 +19,7 @@ package com.viaversion.viaversion.protocols.v1_10to1_11.rewriter;
|
||||
|
||||
import com.viaversion.nbt.tag.ByteTag;
|
||||
import com.viaversion.nbt.tag.CompoundTag;
|
||||
import com.viaversion.nbt.tag.ListTag;
|
||||
import com.viaversion.viaversion.api.connection.UserConnection;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
@@ -55,6 +56,22 @@ public class ItemPacketRewriter1_11 extends ItemRewriter<ClientboundPackets1_9_3
|
||||
item.setAmount(1);
|
||||
}
|
||||
EntityMappings1_11.toClientItem(item);
|
||||
|
||||
if (item == null || item.tag() == null) {
|
||||
return item;
|
||||
}
|
||||
CompoundTag tag = item.tag();
|
||||
|
||||
// 1.10 will display item glint if the list tag is present, 1.11+ only if at least one element is present
|
||||
ListTag enchTag = tag.getListTag("ench");
|
||||
if (enchTag != null && enchTag.isEmpty()) {
|
||||
tag.putBoolean(nbtTagName("clearEnch"), true);
|
||||
|
||||
CompoundTag dummyTag = new CompoundTag();
|
||||
dummyTag.putShort("id", Short.MAX_VALUE);
|
||||
|
||||
enchTag.add(dummyTag);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -63,10 +80,16 @@ public class ItemPacketRewriter1_11 extends ItemRewriter<ClientboundPackets1_9_3
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
if (item.tag() != null && item.tag().contains(nbtTagName())) {
|
||||
item.setAmount(item.tag().<ByteTag>removeUnchecked(nbtTagName()).asByte());
|
||||
if (item.tag().isEmpty()) {
|
||||
item.setTag(null);
|
||||
CompoundTag tag = item.tag();
|
||||
if (tag != null) {
|
||||
if (tag.contains(nbtTagName())) {
|
||||
item.setAmount(tag.<ByteTag>removeUnchecked(nbtTagName()).asByte());
|
||||
if (tag.isEmpty()) {
|
||||
item.setTag(null);
|
||||
}
|
||||
}
|
||||
if (tag.remove(nbtTagName("clearEnch")) != null) {
|
||||
tag.put("ench", new ListTag());
|
||||
}
|
||||
}
|
||||
EntityMappings1_11.toServerItem(item);
|
||||
@@ -78,4 +101,4 @@ public class ItemPacketRewriter1_11 extends ItemRewriter<ClientboundPackets1_9_3
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-36
@@ -72,7 +72,7 @@ public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_9_3.LEVEL_CHUNK, wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11_1To1_12.class);
|
||||
|
||||
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
|
||||
Chunk chunk = wrapper.passthrough(type);
|
||||
@@ -101,38 +101,6 @@ public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9
|
||||
}
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_9_3.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT);
|
||||
map(Types.UNSIGNED_BYTE);
|
||||
map(Types.INT);
|
||||
handler(wrapper -> {
|
||||
UserConnection user = wrapper.user();
|
||||
ClientWorld clientChunks = user.get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientChunks.setEnvironment(dimensionId);
|
||||
|
||||
// Reset recipes
|
||||
if (user.getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_13)) {
|
||||
wrapper.create(ClientboundPackets1_13.UPDATE_RECIPES, packetWrapper -> packetWrapper.write(Types.VAR_INT, 0))
|
||||
.scheduleSend(Protocol1_12_2To1_13.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
registerClientbound(ClientboundPackets1_9_3.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT);
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
new SoundRewriter<>(this, this::getNewSoundId).registerSound(ClientboundPackets1_9_3.SOUND);
|
||||
|
||||
|
||||
@@ -205,9 +173,7 @@ public class Protocol1_11_1To1_12 extends AbstractProtocol<ClientboundPackets1_9
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
userConnection.addEntityTracker(this.getClass(), new EntityTrackerBase(userConnection, EntityTypes1_12.EntityType.PLAYER));
|
||||
if (!userConnection.has(ClientWorld.class)) {
|
||||
userConnection.put(new ClientWorld());
|
||||
}
|
||||
userConnection.addClientWorld(this.getClass(), new ClientWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ import java.util.Set;
|
||||
|
||||
public class AchievementTranslations1_12 {
|
||||
|
||||
private static final Object2ObjectOpenHashMap<String, String> ACHIEVEMENTS = new Object2ObjectOpenHashMap<>(150, 0.99f);
|
||||
private static final Object2ObjectOpenHashMap<String, String> ACHIEVEMENTS = new Object2ObjectOpenHashMap<>(150);
|
||||
private static final Set<String> SPECIAL_ACHIEVEMENTS = new HashSet<>(10);
|
||||
|
||||
static {
|
||||
@@ -196,4 +196,4 @@ public class AchievementTranslations1_12 {
|
||||
return SPECIAL_ACHIEVEMENTS.contains(key);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+41
-2
@@ -17,13 +17,18 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.v1_11_1to1_12.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_12;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_12;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_9;
|
||||
import com.viaversion.viaversion.protocols.v1_11_1to1_12.Protocol1_11_1To1_12;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_9_1to1_9_3.packet.ClientboundPackets1_9_3;
|
||||
import com.viaversion.viaversion.rewriter.EntityRewriter;
|
||||
|
||||
@@ -35,6 +40,40 @@ public class EntityPacketRewriter1_12 extends EntityRewriter<ClientboundPackets1
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_9_3.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT);
|
||||
map(Types.UNSIGNED_BYTE);
|
||||
map(Types.INT);
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11_1To1_12.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
|
||||
// Reset recipes
|
||||
if (wrapper.user().getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_13)) {
|
||||
wrapper.create(ClientboundPackets1_13.UPDATE_RECIPES, packetWrapper -> packetWrapper.write(Types.VAR_INT, 0))
|
||||
.scheduleSend(Protocol1_12_2To1_13.class);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9_3.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT);
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_11_1To1_12.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
if (clientWorld.setEnvironment(dimensionId)) {
|
||||
tracker(wrapper.user()).clearEntities();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_9_3.ADD_ENTITY, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
@@ -62,7 +101,7 @@ public class EntityPacketRewriter1_12 extends EntityRewriter<ClientboundPackets1
|
||||
map(Types.SHORT); // 9 - Velocity X
|
||||
map(Types.SHORT); // 10 - Velocity Y
|
||||
map(Types.SHORT); // 11 - Velocity Z
|
||||
map(Types1_12.ENTITY_DATA_LIST); // 12 - Entity data
|
||||
map(Types1_9.ENTITY_DATA_LIST, Types1_12.ENTITY_DATA_LIST); // 12 - Entity data
|
||||
|
||||
// Track mob and rewrite entity data
|
||||
handler(trackerAndRewriterHandler(Types1_12.ENTITY_DATA_LIST));
|
||||
@@ -70,7 +109,7 @@ public class EntityPacketRewriter1_12 extends EntityRewriter<ClientboundPackets1
|
||||
});
|
||||
|
||||
registerRemoveEntities(ClientboundPackets1_9_3.REMOVE_ENTITIES);
|
||||
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types1_12.ENTITY_DATA_LIST);
|
||||
registerSetEntityData(ClientboundPackets1_9_3.SET_ENTITY_DATA, Types1_9.ENTITY_DATA_LIST, Types1_12.ENTITY_DATA_LIST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+15
-25
@@ -34,6 +34,7 @@ import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.ValueTransformer;
|
||||
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_13;
|
||||
@@ -145,7 +146,7 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
}).scheduleSend(Protocol1_12_2To1_13.class);
|
||||
|
||||
// Send tags packet
|
||||
w.create(ClientboundPackets1_13.UPDATE_TAGS, wrapper -> {
|
||||
final PacketWrapper tagsPacket = w.create(ClientboundPackets1_13.UPDATE_TAGS, wrapper -> {
|
||||
wrapper.write(Types.VAR_INT, MAPPINGS.getBlockTags().size()); // block tags
|
||||
for (Map.Entry<String, int[]> tag : MAPPINGS.getBlockTags().entrySet()) {
|
||||
wrapper.write(Types.STRING, tag.getKey());
|
||||
@@ -164,7 +165,13 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
// Needs copy as other protocols may modify it
|
||||
wrapper.write(Types.VAR_INT_ARRAY_PRIMITIVE, tag.getValue().clone());
|
||||
}
|
||||
}).scheduleSend(Protocol1_12_2To1_13.class);
|
||||
});
|
||||
if (w.user().getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_20_2)) {
|
||||
// Make sure it's included in the configuration packets
|
||||
tagsPacket.send(Protocol1_12_2To1_13.class);
|
||||
} else {
|
||||
tagsPacket.scheduleSend(Protocol1_12_2To1_13.class);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
@@ -173,11 +180,11 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
|
||||
WorldPacketRewriter1_13.register(this);
|
||||
|
||||
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_DISCONNECT.getId(), ClientboundLoginPackets.LOGIN_DISCONNECT.getId(), wrapper -> {
|
||||
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_DISCONNECT, wrapper -> {
|
||||
componentRewriter.processText(wrapper.user(), wrapper.passthrough(Types.COMPONENT));
|
||||
});
|
||||
|
||||
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE.getId(), ClientboundStatusPackets.STATUS_RESPONSE.getId(), new PacketHandlers() {
|
||||
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.STRING);
|
||||
@@ -346,7 +353,7 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
registerClientbound(ClientboundPackets1_12_1.PLACE_GHOST_RECIPE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE);
|
||||
map(Types.UNSIGNED_BYTE);
|
||||
handler(wrapper -> wrapper.write(Types.STRING, "viaversion:legacy/" + wrapper.read(Types.VAR_INT)));
|
||||
}
|
||||
});
|
||||
@@ -401,23 +408,6 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
}
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_12_1.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Dimension ID
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
|
||||
if (Via.getConfig().isServersideBlockConnections()) {
|
||||
ConnectionData.clearBlockStorage(wrapper.user());
|
||||
}
|
||||
});
|
||||
handler(SEND_DECLARE_COMMANDS_AND_TAGS);
|
||||
}
|
||||
});
|
||||
|
||||
registerClientbound(ClientboundPackets1_12_1.SET_OBJECTIVE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
@@ -604,7 +594,7 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
registerServerbound(ServerboundPackets1_13.PLACE_RECIPE, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.BYTE); // Window id
|
||||
map(Types.UNSIGNED_BYTE); // Window id
|
||||
|
||||
handler(wrapper -> {
|
||||
String s = wrapper.read(Types.STRING);
|
||||
@@ -844,9 +834,9 @@ public class Protocol1_12_2To1_13 extends AbstractProtocol<ClientboundPackets1_1
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
userConnection.addEntityTracker(this.getClass(), new EntityTrackerBase(userConnection, EntityTypes1_13.EntityType.PLAYER));
|
||||
userConnection.addClientWorld(this.getClass(), new ClientWorld());
|
||||
|
||||
userConnection.put(new TabCompleteTracker());
|
||||
if (!userConnection.has(ClientWorld.class))
|
||||
userConnection.put(new ClientWorld());
|
||||
userConnection.put(new BlockStorage());
|
||||
if (Via.getConfig().isServersideBlockConnections()) {
|
||||
if (Via.getManager().getProviders().get(BlockConnectionProvider.class) instanceof PacketBlockConnectionProvider) {
|
||||
|
||||
+3
-3
@@ -54,8 +54,8 @@ import java.util.Map.Entry;
|
||||
|
||||
public final class ConnectionData {
|
||||
public static BlockConnectionProvider blockConnectionProvider;
|
||||
static final Object2IntMap<String> KEY_TO_ID = new Object2IntOpenHashMap<>(8582, .99F);
|
||||
static final IntSet OCCLUDING_STATES = new IntOpenHashSet(377, .99F);
|
||||
static final Object2IntMap<String> KEY_TO_ID = new Object2IntOpenHashMap<>(8582);
|
||||
static final IntSet OCCLUDING_STATES = new IntOpenHashSet(377);
|
||||
static Int2ObjectMap<ConnectionHandler> connectionHandlerMap = new Int2ObjectOpenHashMap<>();
|
||||
static Int2ObjectMap<BlockData> blockConnectionData = new Int2ObjectOpenHashMap<>();
|
||||
private static final BlockChangeRecord1_8[] EMPTY_RECORDS = new BlockChangeRecord1_8[0];
|
||||
@@ -173,7 +173,7 @@ public final class ConnectionData {
|
||||
KEY_TO_ID.put(key, id);
|
||||
}
|
||||
|
||||
connectionHandlerMap = new Int2ObjectOpenHashMap<>(3650, .99F);
|
||||
connectionHandlerMap = new Int2ObjectOpenHashMap<>(3650);
|
||||
|
||||
if (!Via.getConfig().isReduceBlockStorageMemory()) {
|
||||
blockConnectionData = new Int2ObjectOpenHashMap<>(2048);
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
|
||||
public class EntityIdMappings1_13 {
|
||||
private static final Int2IntMap ENTITY_TYPES = new Int2IntOpenHashMap(83, .99F);
|
||||
private static final Int2IntMap ENTITY_TYPES = new Int2IntOpenHashMap(83);
|
||||
|
||||
static {
|
||||
ENTITY_TYPES.defaultReturnValue(-1);
|
||||
@@ -121,4 +121,4 @@ public class EntityIdMappings1_13 {
|
||||
public static Int2IntMap getEntityTypes() {
|
||||
return ENTITY_TYPES;
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
-2
@@ -28,6 +28,7 @@ import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_12;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.Protocol1_12_2To1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.blockconnections.ConnectionData;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.data.EntityIdMappings1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_12_2to1_13.data.ParticleIdMappings1_13;
|
||||
import com.viaversion.viaversion.protocols.v1_12to1_12_1.packet.ClientboundPackets1_12_1;
|
||||
@@ -132,7 +133,7 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
|
||||
map(Types.INT); // 2 - Dimension
|
||||
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientChunks = wrapper.user().getClientWorld(Protocol1_12_2To1_13.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientChunks.setEnvironment(dimensionId);
|
||||
});
|
||||
@@ -141,6 +142,24 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_12_1.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Dimension ID
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_12_2To1_13.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
if (clientWorld.setEnvironment(dimensionId)) {
|
||||
if (Via.getConfig().isServersideBlockConnections()) {
|
||||
ConnectionData.clearBlockStorage(wrapper.user());
|
||||
}
|
||||
tracker(wrapper.user()).clearEntities();
|
||||
}
|
||||
});
|
||||
handler(Protocol1_12_2To1_13.SEND_DECLARE_COMMANDS_AND_TAGS);
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_12_1.UPDATE_MOB_EFFECT, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
@@ -235,4 +254,4 @@ public class EntityPacketRewriter1_13 extends EntityRewriter<ClientboundPackets1
|
||||
public EntityType objectTypeFromId(int type) {
|
||||
return EntityTypes1_13.getTypeFromId(type, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-14
@@ -304,23 +304,15 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
|
||||
if (ench != null) {
|
||||
ListTag<CompoundTag> enchantments = new ListTag<>(CompoundTag.class);
|
||||
for (CompoundTag enchEntry : ench) {
|
||||
NumberTag idTag = enchEntry.getNumberTag("id");
|
||||
if (idTag == null) {
|
||||
continue;
|
||||
}
|
||||
short oldId = enchEntry.getShort("id", (short) 0);
|
||||
|
||||
CompoundTag enchantmentEntry = new CompoundTag();
|
||||
short oldId = idTag.asShort();
|
||||
String newId = Protocol1_12_2To1_13.MAPPINGS.getOldEnchantmentsIds().get(oldId);
|
||||
if (newId == null) {
|
||||
newId = "viaversion:legacy/" + oldId;
|
||||
}
|
||||
enchantmentEntry.putString("id", newId);
|
||||
|
||||
NumberTag levelTag = enchEntry.getNumberTag("lvl");
|
||||
if (levelTag != null) {
|
||||
enchantmentEntry.putShort("lvl", levelTag.asShort());
|
||||
}
|
||||
enchantmentEntry.putShort("lvl", enchEntry.getShort("lvl", (short) 0));
|
||||
|
||||
enchantments.add(enchantmentEntry);
|
||||
}
|
||||
@@ -589,10 +581,7 @@ public class ItemPacketRewriter1_13 extends ItemRewriter<ClientboundPackets1_12_
|
||||
}
|
||||
if (oldId != null) {
|
||||
enchEntry.putShort("id", oldId);
|
||||
NumberTag levelTag = enchantmentEntry.getNumberTag("lvl");
|
||||
if (levelTag != null) {
|
||||
enchEntry.putShort("lvl", levelTag.asShort());
|
||||
}
|
||||
enchEntry.putShort("lvl", enchantmentEntry.getShort("lvl", (short) 0));
|
||||
ench.add(enchEntry);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -53,7 +53,7 @@ import java.util.Iterator;
|
||||
import java.util.Optional;
|
||||
|
||||
public class WorldPacketRewriter1_13 {
|
||||
private static final IntSet VALID_BIOMES = new IntOpenHashSet(70, .99F);
|
||||
private static final IntSet VALID_BIOMES = new IntOpenHashSet(70);
|
||||
|
||||
static {
|
||||
// Client will crash if it receives an invalid biome id
|
||||
@@ -325,7 +325,7 @@ public class WorldPacketRewriter1_13 {
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_12_1.LEVEL_CHUNK, wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_12_2To1_13.class);
|
||||
BlockStorage storage = wrapper.user().get(BlockStorage.class);
|
||||
|
||||
ChunkType1_9_3 type = ChunkType1_9_3.forEnvironment(clientWorld.getEnvironment());
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import java.util.Map;
|
||||
|
||||
// TODO Fix memory leak lolz (only a smol one tho)
|
||||
public class BlockStorage implements StorableObject {
|
||||
private static final IntSet WHITELIST = new IntOpenHashSet(46, .99F);
|
||||
private static final IntSet WHITELIST = new IntOpenHashSet(46);
|
||||
private final Map<BlockPosition, ReplacementData> blocks = new HashMap<>();
|
||||
|
||||
static {
|
||||
|
||||
+2
-4
@@ -121,9 +121,7 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
userConnection.addEntityTracker(this.getClass(), new EntityTracker1_14(userConnection));
|
||||
if (!userConnection.has(ClientWorld.class)) {
|
||||
userConnection.put(new ClientWorld());
|
||||
}
|
||||
userConnection.addClientWorld(this.getClass(), new ClientWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -145,4 +143,4 @@ public class Protocol1_13_2To1_14 extends AbstractProtocol<ClientboundPackets1_1
|
||||
public TagRewriter<ClientboundPackets1_13> getTagRewriter() {
|
||||
return tagRewriter;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -204,7 +204,7 @@ public class EntityPacketRewriter1_14 extends EntityRewriter<ClientboundPackets1
|
||||
map(Types.INT); // 2 - Dimension
|
||||
handler(wrapper -> {
|
||||
// Store the player
|
||||
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientChunks = wrapper.user().getClientWorld(Protocol1_13_2To1_14.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientChunks.setEnvironment(dimensionId);
|
||||
});
|
||||
|
||||
+13
-8
@@ -125,7 +125,7 @@ public class WorldPacketRewriter1_14 {
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_13.LEVEL_CHUNK, wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13_2To1_14.class);
|
||||
Chunk chunk = wrapper.read(ChunkType1_13.forEnvironment(clientWorld.getEnvironment()));
|
||||
wrapper.write(ChunkType1_14.TYPE, chunk);
|
||||
|
||||
@@ -282,21 +282,26 @@ public class WorldPacketRewriter1_14 {
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Dimension ID
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
short difficulty = wrapper.read(Types.UNSIGNED_BYTE); // 19w11a removed difficulty from respawn
|
||||
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13_2To1_14.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
|
||||
if (!clientWorld.setEnvironment(dimensionId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
EntityTracker1_14 entityTracker = wrapper.user().getEntityTracker(Protocol1_13_2To1_14.class);
|
||||
entityTracker.clearEntities();
|
||||
|
||||
// The client may reset the center chunk if dimension is changed
|
||||
entityTracker.setForceSendCenterChunk(true);
|
||||
});
|
||||
handler(wrapper -> {
|
||||
short difficulty = wrapper.read(Types.UNSIGNED_BYTE); // 19w11a removed difficulty from respawn
|
||||
|
||||
PacketWrapper difficultyPacket = wrapper.create(ClientboundPackets1_14.CHANGE_DIFFICULTY);
|
||||
difficultyPacket.write(Types.UNSIGNED_BYTE, difficulty);
|
||||
difficultyPacket.write(Types.BOOLEAN, false); // Unknown value added in 19w11a
|
||||
difficultyPacket.scheduleSend(protocol.getClass());
|
||||
});
|
||||
handler(wrapper -> {
|
||||
|
||||
// Manually send the packet and update the viewdistance after
|
||||
wrapper.send(Protocol1_13_2To1_14.class);
|
||||
wrapper.cancel();
|
||||
|
||||
+1
-3
@@ -134,9 +134,7 @@ public class Protocol1_13To1_13_1 extends AbstractProtocol<ClientboundPackets1_1
|
||||
@Override
|
||||
public void init(UserConnection userConnection) {
|
||||
userConnection.addEntityTracker(this.getClass(), new EntityTrackerBase(userConnection, EntityTypes1_13.EntityType.PLAYER));
|
||||
if (!userConnection.has(ClientWorld.class)) {
|
||||
userConnection.put(new ClientWorld());
|
||||
}
|
||||
userConnection.addClientWorld(this.getClass(), new ClientWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+31
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.protocols.v1_13to1_13_1.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityType;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_13;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
@@ -34,6 +35,36 @@ public class EntityPacketRewriter1_13_1 extends EntityRewriter<ClientboundPacket
|
||||
|
||||
@Override
|
||||
protected void registerPackets() {
|
||||
protocol.registerClientbound(ClientboundPackets1_13.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Entity ID
|
||||
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
|
||||
map(Types.INT); // 2 - Dimension
|
||||
|
||||
handler(wrapper -> {
|
||||
// Store the player
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13To1_13_1.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_13.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Dimension ID
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13To1_13_1.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
if (clientWorld.setEnvironment(dimensionId)) {
|
||||
tracker(wrapper.user()).clearEntities();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_13.ADD_ENTITY, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
|
||||
+1
-32
@@ -19,9 +19,6 @@ package com.viaversion.viaversion.protocols.v1_13to1_13_1.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.ClientWorld;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.Chunk;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.ChunkSection;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.DataPalette;
|
||||
import com.viaversion.viaversion.api.minecraft.chunks.PaletteType;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.type.Types;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_13;
|
||||
@@ -35,7 +32,7 @@ public class WorldPacketRewriter1_13_1 {
|
||||
BlockRewriter<ClientboundPackets1_13> blockRewriter = BlockRewriter.legacy(protocol);
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_13.LEVEL_CHUNK, wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
ClientWorld clientWorld = wrapper.user().getClientWorld(Protocol1_13To1_13_1.class);
|
||||
Chunk chunk = wrapper.passthrough(ChunkType1_13.forEnvironment(clientWorld.getEnvironment()));
|
||||
|
||||
blockRewriter.handleChunk(chunk);
|
||||
@@ -84,33 +81,5 @@ public class WorldPacketRewriter1_13_1 {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_13.LOGIN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Entity ID
|
||||
map(Types.UNSIGNED_BYTE); // 1 - Gamemode
|
||||
map(Types.INT); // 2 - Dimension
|
||||
|
||||
handler(wrapper -> {
|
||||
// Store the player
|
||||
ClientWorld clientChunks = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 1);
|
||||
clientChunks.setEnvironment(dimensionId);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
protocol.registerClientbound(ClientboundPackets1_13.RESPAWN, new PacketHandlers() {
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT); // 0 - Dimension ID
|
||||
handler(wrapper -> {
|
||||
ClientWorld clientWorld = wrapper.user().get(ClientWorld.class);
|
||||
int dimensionId = wrapper.get(Types.INT, 0);
|
||||
clientWorld.setEnvironment(dimensionId);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -86,7 +86,10 @@ public class EntityPacketRewriter1_15 extends EntityRewriter<ClientboundPackets1
|
||||
@Override
|
||||
public void register() {
|
||||
map(Types.INT);
|
||||
handler(wrapper -> wrapper.write(Types.LONG, 0L)); // Level Seed
|
||||
handler(wrapper -> {
|
||||
tracker(wrapper.user()).clearEntities();
|
||||
wrapper.write(Types.LONG, 0L); // Level Seed
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+3
-3
@@ -81,14 +81,14 @@ public class Protocol1_15_2To1_16 extends AbstractProtocol<ClientboundPackets1_1
|
||||
new StatisticsRewriter<>(this).register(ClientboundPackets1_15.AWARD_STATS);
|
||||
|
||||
// Login Success
|
||||
registerClientbound(State.LOGIN, ClientboundLoginPackets.GAME_PROFILE.getId(), ClientboundLoginPackets.GAME_PROFILE.getId(), wrapper -> {
|
||||
registerClientbound(State.LOGIN, ClientboundLoginPackets.LOGIN_FINISHED, wrapper -> {
|
||||
// Transform string to a uuid
|
||||
UUID uuid = UUID.fromString(wrapper.read(Types.STRING));
|
||||
wrapper.write(Types.UUID, uuid);
|
||||
});
|
||||
|
||||
// Motd Status - line breaks are no longer allowed for player samples
|
||||
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE.getId(), ClientboundStatusPackets.STATUS_RESPONSE.getId(), wrapper -> {
|
||||
registerClientbound(State.STATUS, ClientboundStatusPackets.STATUS_RESPONSE, wrapper -> {
|
||||
String original = wrapper.passthrough(Types.STRING);
|
||||
JsonObject object = GsonUtil.getGson().fromJson(original, JsonObject.class);
|
||||
JsonObject players = object.getAsJsonObject("players");
|
||||
@@ -263,4 +263,4 @@ public class Protocol1_15_2To1_16 extends AbstractProtocol<ClientboundPackets1_1
|
||||
public TagRewriter<ClientboundPackets1_15> getTagRewriter() {
|
||||
return tagRewriter;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -119,6 +119,8 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
|
||||
map(Types.LONG); // Seed
|
||||
map(Types.UNSIGNED_BYTE); // Gamemode
|
||||
handler(wrapper -> {
|
||||
tracker(wrapper.user()).clearEntities();
|
||||
|
||||
wrapper.write(Types.BYTE, (byte) -1); // Previous gamemode, set to none
|
||||
|
||||
// <= 1.14.4 didn't keep attributes on respawn and 1.15.x always kept them
|
||||
@@ -145,9 +147,8 @@ public class EntityPacketRewriter1_16 extends EntityRewriter<ClientboundPackets1
|
||||
handler(DIMENSION_HANDLER); // Dimension
|
||||
map(Types.LONG); // Seed
|
||||
map(Types.UNSIGNED_BYTE); // Max players
|
||||
handler(playerTrackerHandler());
|
||||
handler(wrapper -> {
|
||||
wrapper.user().getEntityTracker(Protocol1_15_2To1_16.class).addEntity(wrapper.get(Types.INT, 0), EntityTypes1_16.PLAYER);
|
||||
|
||||
final String type = wrapper.read(Types.STRING);// level type
|
||||
wrapper.passthrough(Types.VAR_INT); // View distance
|
||||
wrapper.passthrough(Types.BOOLEAN); // Reduced debug info
|
||||
|
||||
+2
@@ -72,6 +72,8 @@ public class EntityPacketRewriter1_16_2 extends EntityRewriter<ClientboundPacket
|
||||
protocol.registerClientbound(ClientboundPackets1_16.RESPAWN, wrapper -> {
|
||||
String dimensionType = wrapper.read(Types.STRING);
|
||||
wrapper.write(Types.NAMED_COMPOUND_TAG, getDimensionData(dimensionType));
|
||||
|
||||
tracker(wrapper.user()).clearEntities();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -37,7 +37,6 @@ import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ServerboundPacke
|
||||
import com.viaversion.viaversion.protocols.v1_16_4to1_17.rewriter.EntityPacketRewriter1_17;
|
||||
import com.viaversion.viaversion.protocols.v1_16_4to1_17.rewriter.ItemPacketRewriter1_17;
|
||||
import com.viaversion.viaversion.protocols.v1_16_4to1_17.rewriter.WorldPacketRewriter1_17;
|
||||
import com.viaversion.viaversion.protocols.v1_16_4to1_17.storage.InventoryAcknowledgements;
|
||||
import com.viaversion.viaversion.rewriter.SoundRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StatisticsRewriter;
|
||||
import com.viaversion.viaversion.rewriter.TagRewriter;
|
||||
@@ -68,7 +67,7 @@ public final class Protocol1_16_4To1_17 extends AbstractProtocol<ClientboundPack
|
||||
wrapper.write(Types.STRING, type.resourceLocation());
|
||||
|
||||
// Id conversion
|
||||
tagRewriter.handle(wrapper, tagRewriter.getRewriter(type), tagRewriter.getNewTags(type));
|
||||
tagRewriter.handle(wrapper, type);
|
||||
|
||||
// Stop iterating after entity types
|
||||
if (type == RegistryType.ENTITY) {
|
||||
@@ -192,7 +191,6 @@ public final class Protocol1_16_4To1_17 extends AbstractProtocol<ClientboundPack
|
||||
@Override
|
||||
public void init(UserConnection user) {
|
||||
addEntityTracker(user, new EntityTrackerBase(user, EntityTypes1_17.PLAYER));
|
||||
user.put(new InventoryAcknowledgements());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -214,4 +212,4 @@ public final class Protocol1_16_4To1_17 extends AbstractProtocol<ClientboundPack
|
||||
public TagRewriter<ClientboundPackets1_16_2> getTagRewriter() {
|
||||
return tagRewriter;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 179 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user