Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-26 00:00:28 +01:00
Once again refactor structured data storage
Optionals are no more
Dieser Commit ist enthalten in:
Ursprung
6ffa24b50b
Commit
f68aed464d
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.data;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
final class EmptyStructuredData<T> implements StructuredData<T> {
|
||||
|
||||
private final StructuredDataKey<T> key;
|
||||
private int id;
|
||||
|
||||
EmptyStructuredData(final StructuredDataKey<T> key, final int id) {
|
||||
this.key = key;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(final T value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(final int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructuredDataKey<T> key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T value() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.data;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
final class FilledStructuredData<T> implements StructuredData<T> {
|
||||
|
||||
private final StructuredDataKey<T> key;
|
||||
private T value;
|
||||
private int id;
|
||||
|
||||
FilledStructuredData(final StructuredDataKey<T> key, final T value, final int id) {
|
||||
Preconditions.checkNotNull(key);
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(final T value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(final ByteBuf buffer) throws Exception {
|
||||
key.type().write(buffer, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(final int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StructuredDataKey<T> key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
}
|
@ -22,53 +22,59 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.data;
|
||||
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.util.IdHolder;
|
||||
import com.viaversion.viaversion.util.Unit;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class StructuredData<T> implements IdHolder {
|
||||
public interface StructuredData<T> extends IdHolder {
|
||||
|
||||
private final StructuredDataKey<T> key;
|
||||
private T value;
|
||||
private int id;
|
||||
|
||||
public StructuredData(final StructuredDataKey<T> key, final T value, final int id) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
/**
|
||||
* Returns filled structured data, equivalent to an Optional with a value in vanilla.
|
||||
*
|
||||
* @param key serializer key
|
||||
* @param value value
|
||||
* @param id serializer id
|
||||
* @param <T> serializer type
|
||||
* @return filled structured data
|
||||
*/
|
||||
static <T> StructuredData<T> of(final StructuredDataKey<T> key, final T value, final int id) {
|
||||
return new FilledStructuredData<>(key, value, id);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return key.type() == Type.UNIT;
|
||||
/**
|
||||
* Returns empty structured data, equivalent to an empty Optional in vanilla.
|
||||
*
|
||||
* @param key serializer key
|
||||
* @param id serializer id
|
||||
* @return empty structured data
|
||||
*/
|
||||
static <T> StructuredData<T> empty(final StructuredDataKey<T> key, final int id) {
|
||||
return new EmptyStructuredData<>(key, id);
|
||||
}
|
||||
|
||||
public void setValue(final T value) {
|
||||
if (value != null && !key.type().getOutputClass().isAssignableFrom(value.getClass())) {
|
||||
throw new IllegalArgumentException("Item data type and value are incompatible. Type=" + key
|
||||
+ ", value=" + value + " (" + value.getClass().getSimpleName() + ")");
|
||||
}
|
||||
this.value = value;
|
||||
void setValue(final T value);
|
||||
|
||||
void write(final ByteBuf buffer) throws Exception;
|
||||
|
||||
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.
|
||||
*
|
||||
* @return true if the structured data is present
|
||||
*/
|
||||
default boolean isPresent() {
|
||||
return !isEmpty();
|
||||
}
|
||||
|
||||
public void write(final ByteBuf buffer) throws Exception {
|
||||
key.type().write(buffer, value);
|
||||
}
|
||||
|
||||
public void setId(final int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public StructuredDataKey<T> key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public T value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* Returns whether the structured data is empty. Not to be confused with a null value.
|
||||
*
|
||||
* @return true if the structured data is empty
|
||||
*/
|
||||
boolean isEmpty();
|
||||
}
|
||||
|
@ -23,96 +23,106 @@
|
||||
package com.viaversion.viaversion.api.minecraft.data;
|
||||
|
||||
import com.viaversion.viaversion.api.Via;
|
||||
import com.viaversion.viaversion.api.data.FullMappings;
|
||||
import com.viaversion.viaversion.api.protocol.Protocol;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.util.Optional;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class StructuredDataContainer {
|
||||
|
||||
private final Int2ObjectMap<Optional<StructuredData<?>>> data; // Bless Optionals in a map
|
||||
private final Map<StructuredDataKey<?>, StructuredData<?>> data;
|
||||
private FullMappings lookup;
|
||||
private boolean mappedNames;
|
||||
|
||||
public StructuredDataContainer(final Int2ObjectMap<Optional<StructuredData<?>>> data) {
|
||||
public StructuredDataContainer(final Map<StructuredDataKey<?>, StructuredData<?>> data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public StructuredDataContainer() {
|
||||
this(new Int2ObjectOpenHashMap<>());
|
||||
this(new Reference2ObjectOpenHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns structured data by id. You might want to call {@link #contains(int)} first.
|
||||
* Returns structured data by id if present.
|
||||
*
|
||||
* @param id serializer id
|
||||
* @param <T> data type
|
||||
* @return structured data
|
||||
*/
|
||||
public Optional<StructuredData<?>> get(final int id) {
|
||||
return this.data.getOrDefault(id, Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns structured data by id. You might want to call {@link #contains(Protocol, StructuredDataKey)} first.
|
||||
*
|
||||
* @param protocol protocol to retreive the id of the serializer from
|
||||
* @param key serializer id
|
||||
* @param <T> data type
|
||||
* @return structured data
|
||||
*/
|
||||
public <T> Optional<StructuredData<T>> get(final Protocol<?, ?, ?, ?> protocol, final StructuredDataKey<T> key) {
|
||||
final Optional<StructuredData<?>> data = this.data.getOrDefault(serializerId(protocol, key), Optional.empty());
|
||||
public @Nullable <T> StructuredData<T> get(final StructuredDataKey<T> key) {
|
||||
//noinspection unchecked
|
||||
return data.map(value -> (StructuredData<T>) value);
|
||||
return (StructuredData<T>) this.data.get(key);
|
||||
}
|
||||
|
||||
public void add(final StructuredData<?> data) {
|
||||
this.data.put(data.id(), Optional.of(data));
|
||||
/**
|
||||
* Returns structured data by id if not empty.
|
||||
*
|
||||
* @param key serializer id
|
||||
* @param <T> data type
|
||||
* @return structured data if not empty
|
||||
*/
|
||||
public @Nullable <T> StructuredData<T> getNonEmpty(final StructuredDataKey<T> key) {
|
||||
//noinspection unchecked
|
||||
final StructuredData<T> data = (StructuredData<T>) this.data.get(key);
|
||||
return data != null && data.isPresent() ? data : null;
|
||||
}
|
||||
|
||||
public <T> void add(final Protocol<?, ?, ?, ?> protocol, final StructuredDataKey<T> key, final T value) {
|
||||
final int id = serializerId(protocol, key);
|
||||
public <T> void add(final StructuredDataKey<T> key, final T value) {
|
||||
final int id = serializerId(key);
|
||||
if (id != -1) {
|
||||
add(new StructuredData<>(key, value, id));
|
||||
this.data.put(key, StructuredData.of(key, value, id));
|
||||
}
|
||||
}
|
||||
|
||||
public void addEmpty(final Protocol<?, ?, ?, ?> protocol, final StructuredDataKey<?> key) {
|
||||
final int id = serializerId(protocol, key);
|
||||
if (id != -1) {
|
||||
this.data.put(id, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(final int id) {
|
||||
this.data.remove(id);
|
||||
}
|
||||
|
||||
public void removeDefault(final int id) {
|
||||
public void addEmpty(final StructuredDataKey<?> key) {
|
||||
// Empty optional to override the Minecraft default
|
||||
this.data.put(id, Optional.empty());
|
||||
this.data.put(key, StructuredData.empty(key, serializerId(key)));
|
||||
}
|
||||
|
||||
public boolean contains(final int id) {
|
||||
return this.data.containsKey(id);
|
||||
/**
|
||||
* Removes and returns structured data by the given key.
|
||||
*
|
||||
* @param key serializer key
|
||||
* @param <T> data type
|
||||
* @return removed structured data
|
||||
*/
|
||||
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 boolean contains(final Protocol<?, ?, ?, ?> protocol, final StructuredDataKey<?> key) {
|
||||
return this.data.containsKey(serializerId(protocol, key));
|
||||
public boolean contains(final StructuredDataKey<?> key) {
|
||||
return this.data.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the lookup for serializer ids. Required to call most of the other methods.
|
||||
*
|
||||
* @param protocol protocol to retreive the id of the serializer from
|
||||
* @param mappedNames if the names are mapped (true if structures from the mapped version are added, false for the unmapped version)
|
||||
*/
|
||||
public void setIdLookup(final Protocol<?, ?, ?, ?> protocol, final boolean mappedNames) {
|
||||
this.lookup = protocol.getMappingData().getDataComponentSerializerMappings();
|
||||
this.mappedNames = mappedNames;
|
||||
}
|
||||
|
||||
public StructuredDataContainer copy() {
|
||||
return new StructuredDataContainer(new Int2ObjectOpenHashMap<>(data));
|
||||
final StructuredDataContainer copy = new StructuredDataContainer(new Reference2ObjectOpenHashMap<>(data));
|
||||
copy.lookup = this.lookup;
|
||||
return copy;
|
||||
}
|
||||
|
||||
private int serializerId(final Protocol<?, ?, ?, ?> protocol, final StructuredDataKey<?> key) {
|
||||
final int id = protocol.getMappingData().getDataComponentSerializerMappings().mappedId(key.identifier());
|
||||
private int serializerId(final StructuredDataKey<?> key) {
|
||||
final int id = mappedNames ? lookup.mappedId(key.identifier()) : lookup.id(key.identifier());
|
||||
if (id == -1) {
|
||||
Via.getPlatform().getLogger().severe("Could not find item data serializer for type " + key);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public Int2ObjectMap<Optional<StructuredData<?>>> data() {
|
||||
public Map<StructuredDataKey<?>, StructuredData<?>> data() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -22,24 +22,25 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.type.types.item;
|
||||
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredData;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataContainer;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
|
||||
import com.viaversion.viaversion.api.minecraft.item.Item;
|
||||
import com.viaversion.viaversion.api.minecraft.item.StructuredItem;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import java.util.Optional;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class ItemType1_20_5 extends Type<Item> {
|
||||
|
||||
private final Type<StructuredData<?>> dataType;
|
||||
private final StructuredDataType dataType;
|
||||
|
||||
public ItemType1_20_5(final Type<StructuredData<?>> itemDataType) {
|
||||
public ItemType1_20_5(final StructuredDataType dataType) {
|
||||
super(Item.class);
|
||||
this.dataType = itemDataType;
|
||||
this.dataType = dataType;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,26 +51,30 @@ public class ItemType1_20_5 extends Type<Item> {
|
||||
}
|
||||
|
||||
final int id = Type.VAR_INT.readPrimitive(buffer);
|
||||
final Int2ObjectMap<Optional<StructuredData<?>>> data = readData(buffer);
|
||||
final Map<StructuredDataKey<?>, StructuredData<?>> data = readData(buffer);
|
||||
return new StructuredItem(id, amount, new StructuredDataContainer(data));
|
||||
}
|
||||
|
||||
private Int2ObjectMap<Optional<StructuredData<?>>> readData(final ByteBuf buffer) throws Exception {
|
||||
private Map<StructuredDataKey<?>, StructuredData<?>> readData(final ByteBuf buffer) throws Exception {
|
||||
final int valuesSize = Type.VAR_INT.readPrimitive(buffer);
|
||||
final int markersSize = Type.VAR_INT.readPrimitive(buffer);
|
||||
if (valuesSize == 0 && markersSize == 0) {
|
||||
return new Int2ObjectOpenHashMap<>();
|
||||
return new Reference2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
final Int2ObjectMap<Optional<StructuredData<?>>> map = new Int2ObjectOpenHashMap<>(valuesSize + markersSize);
|
||||
final Map<StructuredDataKey<?>, StructuredData<?>> map = new Reference2ObjectOpenHashMap<>(valuesSize + markersSize);
|
||||
for (int i = 0; i < valuesSize; i++) {
|
||||
final StructuredData<?> value = dataType.read(buffer);
|
||||
map.put(value.id(), Optional.of(value));
|
||||
final StructuredDataKey<?> key = dataType.key(value.id());
|
||||
Preconditions.checkNotNull(key, "No data component serializer found for $s", value);
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
for (int i = 0; i < markersSize; i++) {
|
||||
final int key = Type.VAR_INT.readPrimitive(buffer);
|
||||
map.put(key, Optional.empty());
|
||||
final int id = Type.VAR_INT.readPrimitive(buffer);
|
||||
final StructuredDataKey<?> key = dataType.key(id);
|
||||
Preconditions.checkNotNull(key, "No data component serializer found for empty id $s", id);
|
||||
map.put(key, StructuredData.empty(key, id));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
@ -84,11 +89,11 @@ public class ItemType1_20_5 extends Type<Item> {
|
||||
buffer.writeByte(object.amount());
|
||||
Type.VAR_INT.writePrimitive(buffer, object.identifier());
|
||||
|
||||
final Int2ObjectMap<Optional<StructuredData<?>>> data = object.structuredData().data();
|
||||
final Map<StructuredDataKey<?>, StructuredData<?>> data = object.structuredData().data();
|
||||
int valuesSize = 0;
|
||||
int markersSize = 0;
|
||||
for (final Int2ObjectMap.Entry<Optional<StructuredData<?>>> entry : data.int2ObjectEntrySet()) {
|
||||
if (entry.getValue().isPresent()) {
|
||||
for (final StructuredData<?> value : data.values()) {
|
||||
if (value.isPresent()) {
|
||||
valuesSize++;
|
||||
} else {
|
||||
markersSize++;
|
||||
@ -98,14 +103,14 @@ public class ItemType1_20_5 extends Type<Item> {
|
||||
Type.VAR_INT.writePrimitive(buffer, valuesSize);
|
||||
Type.VAR_INT.writePrimitive(buffer, markersSize);
|
||||
|
||||
for (final Int2ObjectMap.Entry<Optional<StructuredData<?>>> entry : data.int2ObjectEntrySet()) {
|
||||
if (entry.getValue().isPresent()) {
|
||||
dataType.write(buffer, entry.getValue().get());
|
||||
for (final StructuredData<?> value : data.values()) {
|
||||
if (value.isPresent()) {
|
||||
dataType.write(buffer, value);
|
||||
}
|
||||
}
|
||||
for (final Int2ObjectMap.Entry<Optional<StructuredData<?>>> entry : data.int2ObjectEntrySet()) {
|
||||
if (!entry.getValue().isPresent()) {
|
||||
Type.VAR_INT.writePrimitive(buffer, entry.getIntKey());
|
||||
for (final StructuredData<?> value : data.values()) {
|
||||
if (value.isEmpty()) {
|
||||
Type.VAR_INT.writePrimitive(buffer, value.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import com.viaversion.viaversion.api.type.Type;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class StructuredDataType extends Type<StructuredData<?>> {
|
||||
|
||||
@ -55,8 +56,12 @@ public class StructuredDataType extends Type<StructuredData<?>> {
|
||||
throw new IllegalArgumentException("No data component serializer found for id " + id);
|
||||
}
|
||||
|
||||
public @Nullable StructuredDataKey<?> key(final int id) {
|
||||
return types.get(id);
|
||||
}
|
||||
|
||||
private <T> StructuredData<T> readData(final ByteBuf buffer, final StructuredDataKey<T> key, final int id) throws Exception {
|
||||
return new StructuredData<>(key, key.type().read(buffer), id);
|
||||
return StructuredData.of(key, key.type().read(buffer), id);
|
||||
}
|
||||
|
||||
public DataFiller filler(final Protocol<?, ?, ?, ?> protocol) {
|
||||
|
@ -38,8 +38,8 @@ public final class Types1_20_5 {
|
||||
|
||||
// Most of these are only safe to use after protocol loading
|
||||
public static final ParticleType PARTICLE = new ParticleType();
|
||||
public static final StructuredDataType ITEM_DATA = new StructuredDataType();
|
||||
public static final Type<Item> ITEM = new ItemType1_20_5(ITEM_DATA);
|
||||
public static final StructuredDataType STRUCTURED_DATA = new StructuredDataType();
|
||||
public static final Type<Item> ITEM = new ItemType1_20_5(STRUCTURED_DATA);
|
||||
public static final Type<Item[]> ITEM_ARRAY = new ArrayType<>(ITEM);
|
||||
public static final MetaTypes1_20_5 META_TYPES = new MetaTypes1_20_5(PARTICLE);
|
||||
public static final Type<Metadata> METADATA = new MetadataType(META_TYPES);
|
||||
|
@ -29,9 +29,10 @@ fun ShadowJar.configureRelocations() {
|
||||
}
|
||||
|
||||
fun ShadowJar.configureExcludes() {
|
||||
// FastUtil - we only want object, int, and reference maps
|
||||
// FastUtil - we only want object, int, and certain reference maps
|
||||
// Object types
|
||||
exclude("it/unimi/dsi/fastutil/*/*Reference*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*2Reference*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Reference2Int*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Boolean*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Byte*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Short*")
|
||||
@ -48,4 +49,6 @@ fun ShadowJar.configureExcludes() {
|
||||
exclude("it/unimi/dsi/fastutil/*/*Big*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Synchronized*")
|
||||
exclude("it/unimi/dsi/fastutil/*/*Unmodifiable*")
|
||||
// More
|
||||
exclude("it/unimi/dsi/fastutil/io/TextIO")
|
||||
}
|
||||
|
@ -23,19 +23,11 @@ import com.viaversion.viaversion.api.data.MappingDataBase;
|
||||
import com.viaversion.viaversion.api.minecraft.RegistryType;
|
||||
import com.viaversion.viaversion.api.minecraft.data.StructuredDataKey;
|
||||
import com.viaversion.viaversion.api.minecraft.entities.EntityTypes1_20_5;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.BannerPattern;
|
||||
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.DyedColor;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.GameProfile;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.LodestoneTarget;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.WrittenBook;
|
||||
import com.viaversion.viaversion.api.protocol.AbstractProtocol;
|
||||
import com.viaversion.viaversion.api.protocol.packet.State;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.PacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.protocol.packet.provider.SimplePacketTypesProvider;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.minecraft.item.data.Enchantments;
|
||||
import com.viaversion.viaversion.api.type.types.misc.ParticleType;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
import com.viaversion.viaversion.data.entity.EntityTrackerBase;
|
||||
@ -120,7 +112,7 @@ public final class Protocol1_20_5To1_20_3 extends AbstractProtocol<ClientboundPa
|
||||
.reader("vibration", ParticleType.Readers.VIBRATION1_20_3)
|
||||
.reader("sculk_charge", ParticleType.Readers.SCULK_CHARGE)
|
||||
.reader("shriek", ParticleType.Readers.SHRIEK);
|
||||
Types1_20_5.ITEM_DATA.filler(this)
|
||||
Types1_20_5.STRUCTURED_DATA.filler(this)
|
||||
.add(StructuredDataKey.CUSTOM_DATA)
|
||||
.add(StructuredDataKey.DAMAGE)
|
||||
.add(StructuredDataKey.UNBREAKABLE)
|
||||
|
@ -49,7 +49,6 @@ import com.viaversion.viaversion.util.Key;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<ClientboundPacket1_20_3, ServerboundPacket1_20_5, Protocol1_20_5To1_20_3> {
|
||||
@ -189,7 +188,10 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
public Item toOldItem(final Item item) {
|
||||
// Start out with custom data and add the rest on top
|
||||
final StructuredDataContainer data = item.structuredData();
|
||||
final CompoundTag tag = data.get(protocol, StructuredDataKey.CUSTOM_DATA).map(StructuredData::value).orElse(new CompoundTag());
|
||||
data.setIdLookup(protocol, true);
|
||||
|
||||
final StructuredData<CompoundTag> customData = data.getNonEmpty(StructuredDataKey.CUSTOM_DATA);
|
||||
final CompoundTag tag = customData != null ? customData.value() : new CompoundTag();
|
||||
|
||||
// TODO
|
||||
|
||||
@ -200,6 +202,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
final CompoundTag tag = old.tag();
|
||||
final StructuredItem item = new StructuredItem(old.identifier(), (byte) old.amount(), new StructuredDataContainer());
|
||||
final StructuredDataContainer data = item.structuredData();
|
||||
data.setIdLookup(protocol, true);
|
||||
if (tag == null) {
|
||||
return item;
|
||||
}
|
||||
@ -208,19 +211,19 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
final NumberTag damage = tag.getNumberTag("Damage");
|
||||
if (damage != null && damage.asInt() != 0) {
|
||||
tag.remove("Damage");
|
||||
data.add(protocol, StructuredDataKey.DAMAGE, damage.asInt());
|
||||
data.add(StructuredDataKey.DAMAGE, damage.asInt());
|
||||
}
|
||||
|
||||
final NumberTag repairCost = tag.getNumberTag("RepairCost");
|
||||
if (repairCost != null && repairCost.asInt() != 0) {
|
||||
tag.remove("RepairCost");
|
||||
data.add(protocol, StructuredDataKey.REPAIR_COST, repairCost.asInt());
|
||||
data.add(StructuredDataKey.REPAIR_COST, repairCost.asInt());
|
||||
}
|
||||
|
||||
final NumberTag customModelData = tag.getNumberTag("CustomModelData");
|
||||
if (customModelData != null) {
|
||||
tag.remove("CustomModelData");
|
||||
data.add(protocol, StructuredDataKey.CUSTOM_MODEL_DATA, customModelData.asInt());
|
||||
data.add(StructuredDataKey.CUSTOM_MODEL_DATA, customModelData.asInt());
|
||||
}
|
||||
|
||||
final CompoundTag blockState = tag.getCompoundTag("BlockStateTag");
|
||||
@ -232,13 +235,13 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
properties.put(entry.getKey(), ((StringTag) entry.getValue()).getValue());
|
||||
}
|
||||
}
|
||||
data.add(protocol, StructuredDataKey.BLOCK_STATE, new BlockStateProperties(properties));
|
||||
data.add(StructuredDataKey.BLOCK_STATE, new BlockStateProperties(properties));
|
||||
}
|
||||
|
||||
final CompoundTag entityTag = tag.getCompoundTag("EntityTag");
|
||||
if (entityTag != null) {
|
||||
tag.remove("EntityTag");
|
||||
data.add(protocol, StructuredDataKey.ENTITY_DATA, entityTag);
|
||||
data.add(StructuredDataKey.ENTITY_DATA, entityTag);
|
||||
}
|
||||
|
||||
final CompoundTag blockEntityTag = tag.getCompoundTag("BlockEntityTag");
|
||||
@ -255,62 +258,62 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
if (unbreakable != null && unbreakable.asBoolean()) {
|
||||
tag.remove("Unbreakable");
|
||||
if ((hideFlagsValue & 0x04) != 0) {
|
||||
data.add(protocol, StructuredDataKey.UNBREAKABLE, true); // TODO Value is hide, should have a wrapper
|
||||
data.add(StructuredDataKey.UNBREAKABLE, true); // TODO Value is hide, should have a wrapper
|
||||
} else {
|
||||
data.addEmpty(protocol, StructuredDataKey.UNBREAKABLE);
|
||||
data.addEmpty(StructuredDataKey.UNBREAKABLE);
|
||||
}
|
||||
}
|
||||
|
||||
updateEnchantments(data, tag, "Enchantments", StructuredDataKey.ENCHANTMENTS, (hideFlagsValue & 0x01) != 0);
|
||||
updateEnchantments(data, tag, "StoredEnchantments", StructuredDataKey.STORED_ENCHANTMENTS, (hideFlagsValue & 0x20) != 0);
|
||||
updateEnchantments(data, tag, "Enchantments", StructuredDataKey.ENCHANTMENTS, (hideFlagsValue & 0x01) == 0);
|
||||
updateEnchantments(data, tag, "StoredEnchantments", StructuredDataKey.STORED_ENCHANTMENTS, (hideFlagsValue & 0x20) == 0);
|
||||
|
||||
// TODO
|
||||
// tructuredDataKey.CUSTOM_NAME
|
||||
// tructuredDataKey.LORE
|
||||
// tructuredDataKey.CAN_PLACE_ON
|
||||
// tructuredDataKey.CAN_BREAK
|
||||
// tructuredDataKey.ATTRIBUTE_MODIFIERS
|
||||
// tructuredDataKey.HIDE_ADDITIONAL_TOOLTIP
|
||||
// tructuredDataKey.REPAIR_COST
|
||||
// tructuredDataKey.CREATIVE_SLOT_LOCK
|
||||
// tructuredDataKey.INTANGIBLE_PROJECTILE
|
||||
// tructuredDataKey.DYED_COLOR
|
||||
// tructuredDataKey.MAP_COLOR
|
||||
// tructuredDataKey.MAP_ID
|
||||
// tructuredDataKey.MAP_DECORATIONS
|
||||
// tructuredDataKey.MAP_POST_PROCESSING
|
||||
// tructuredDataKey.CHARGED_PROJECTILES
|
||||
// tructuredDataKey.BUNDLE_CONTENTS
|
||||
// tructuredDataKey.POTION_CONTENTS
|
||||
// tructuredDataKey.SUSPICIOUS_STEW_EFFECTS
|
||||
// tructuredDataKey.WRITABLE_BOOK_CONTENT
|
||||
// tructuredDataKey.WRITTEN_BOOK_CONTENT
|
||||
// tructuredDataKey.TRIM
|
||||
// tructuredDataKey.DEBUG_STICK_STATE
|
||||
// tructuredDataKey.BUCKET_ENTITY_DATA
|
||||
// tructuredDataKey.BLOCK_ENTITY_DATA
|
||||
// tructuredDataKey.INSTRUMENT
|
||||
// tructuredDataKey.RECIPES
|
||||
// tructuredDataKey.LODESTONE_TARGET
|
||||
// tructuredDataKey.FIREWORK_EXPLOSION
|
||||
// tructuredDataKey.FIREWORKS
|
||||
// tructuredDataKey.PROFILE
|
||||
// tructuredDataKey.NOTE_BLOCK_SOUND
|
||||
// tructuredDataKey.BANNER_PATTERNS
|
||||
// tructuredDataKey.BASE_COLOR
|
||||
// tructuredDataKey.POT_DECORATIONS
|
||||
// tructuredDataKey.CONTAINER
|
||||
// tructuredDataKey.BEES
|
||||
// tructuredDataKey.LOCK
|
||||
// tructuredDataKey.CONTAINER_LOOT
|
||||
// StructuredDataKey.CUSTOM_NAME
|
||||
// StructuredDataKey.LORE
|
||||
// StructuredDataKey.CAN_PLACE_ON
|
||||
// StructuredDataKey.CAN_BREAK
|
||||
// StructuredDataKey.ATTRIBUTE_MODIFIERS
|
||||
// StructuredDataKey.HIDE_ADDITIONAL_TOOLTIP
|
||||
// StructuredDataKey.REPAIR_COST
|
||||
// StructuredDataKey.CREATIVE_SLOT_LOCK
|
||||
// StructuredDataKey.INTANGIBLE_PROJECTILE
|
||||
// StructuredDataKey.DYED_COLOR
|
||||
// StructuredDataKey.MAP_COLOR
|
||||
// StructuredDataKey.MAP_ID
|
||||
// StructuredDataKey.MAP_DECORATIONS
|
||||
// StructuredDataKey.MAP_POST_PROCESSING
|
||||
// StructuredDataKey.CHARGED_PROJECTILES
|
||||
// StructuredDataKey.BUNDLE_CONTENTS
|
||||
// StructuredDataKey.POTION_CONTENTS
|
||||
// StructuredDataKey.SUSPICIOUS_STEW_EFFECTS
|
||||
// StructuredDataKey.WRITABLE_BOOK_CONTENT
|
||||
// StructuredDataKey.WRITTEN_BOOK_CONTENT
|
||||
// StructuredDataKey.TRIM
|
||||
// StructuredDataKey.DEBUG_STICK_STATE
|
||||
// StructuredDataKey.BUCKET_ENTITY_DATA
|
||||
// StructuredDataKey.BLOCK_ENTITY_DATA
|
||||
// StructuredDataKey.INSTRUMENT
|
||||
// StructuredDataKey.RECIPES
|
||||
// StructuredDataKey.LODESTONE_TARGET
|
||||
// StructuredDataKey.FIREWORK_EXPLOSION
|
||||
// StructuredDataKey.FIREWORKS
|
||||
// StructuredDataKey.PROFILE
|
||||
// StructuredDataKey.NOTE_BLOCK_SOUND
|
||||
// StructuredDataKey.BANNER_PATTERNS
|
||||
// StructuredDataKey.BASE_COLOR
|
||||
// StructuredDataKey.POT_DECORATIONS
|
||||
// StructuredDataKey.CONTAINER
|
||||
// StructuredDataKey.BEES
|
||||
// StructuredDataKey.LOCK
|
||||
// StructuredDataKey.CONTAINER_LOOT
|
||||
|
||||
// Add the rest as custom data
|
||||
data.add(protocol, StructuredDataKey.CUSTOM_DATA, tag);
|
||||
data.add(StructuredDataKey.CUSTOM_DATA, tag);
|
||||
return item;
|
||||
}
|
||||
|
||||
private void updateEnchantments(final StructuredDataContainer data, final CompoundTag tag, final String key,
|
||||
final StructuredDataKey<Enchantments> newKey, final boolean hide) {
|
||||
final StructuredDataKey<Enchantments> newKey, final boolean show) {
|
||||
final ListTag enchantmentsTag = tag.getListTag(key);
|
||||
if (enchantmentsTag == null) {
|
||||
return;
|
||||
@ -318,7 +321,7 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
|
||||
tag.remove(key);
|
||||
|
||||
final Enchantments enchantments = new Enchantments(new Int2IntOpenHashMap(), !hide);
|
||||
final Enchantments enchantments = new Enchantments(new Int2IntOpenHashMap(), show);
|
||||
for (final Tag enchantment : enchantmentsTag) {
|
||||
if (!(enchantment instanceof CompoundTag)) {
|
||||
continue;
|
||||
@ -339,11 +342,11 @@ public final class BlockItemPacketRewriter1_20_5 extends ItemRewriter<Clientboun
|
||||
enchantments.enchantments().put(intId, lvl.asInt());
|
||||
}
|
||||
|
||||
data.add(protocol, newKey, enchantments);
|
||||
data.add(newKey, enchantments);
|
||||
|
||||
// Add glint if none of the enchantments were valid
|
||||
if (enchantments.size() == 0 && !enchantmentsTag.isEmpty()) {
|
||||
data.add(protocol, StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, true);
|
||||
data.add(StructuredDataKey.ENCHANTMENT_GLINT_OVERRIDE, true);
|
||||
}
|
||||
}
|
||||
}
|
@ -50,8 +50,6 @@ public class ItemRewriter<C extends ClientboundPacketType, S extends Serverbound
|
||||
this(protocol, itemType, itemArrayType, itemType, itemArrayType);
|
||||
}
|
||||
|
||||
// These two methods always return the same item instance *for now*
|
||||
// It is made this way, so it's easy to handle new instance creation/implementation changes
|
||||
@Override
|
||||
public @Nullable Item handleItemToClient(@Nullable Item item) {
|
||||
if (item == null) return null;
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.data.MappingData;
|
||||
import com.viaversion.viaversion.api.data.Mappings;
|
||||
import com.viaversion.viaversion.api.data.ParticleMappings;
|
||||
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.protocol.packet.ClientboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.packet.PacketWrapper;
|
||||
import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandler;
|
||||
import com.viaversion.viaversion.api.protocol.remapper.PacketHandlers;
|
||||
import com.viaversion.viaversion.api.rewriter.RewriterBase;
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public class StructuredItemRewriter<C extends ClientboundPacketType, S extends ServerboundPacketType,
|
||||
T extends Protocol<C, ?, ?, S>> extends ItemRewriter<C, S, T> {
|
||||
|
||||
public StructuredItemRewriter(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType, Type<Item> mappedItemType, Type<Item[]> mappedItemArrayType) {
|
||||
super(protocol, itemType, itemArrayType, mappedItemType, mappedItemArrayType);
|
||||
}
|
||||
|
||||
public StructuredItemRewriter(T protocol, Type<Item> itemType, Type<Item[]> itemArrayType) {
|
||||
super(protocol, itemType, itemArrayType, itemType, itemArrayType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Item handleItemToClient(@Nullable Item item) {
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final MappingData mappingData = protocol.getMappingData();
|
||||
if (mappingData != null) {
|
||||
if (mappingData.getItemMappings() != null) {
|
||||
item.setIdentifier(mappingData.getNewItemId(item.identifier()));
|
||||
}
|
||||
if (mappingData.getDataComponentSerializerMappings() != null) {
|
||||
item.structuredData().setIdLookup(protocol, false);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Item handleItemToServer(@Nullable Item item) {
|
||||
if (item == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final MappingData mappingData = protocol.getMappingData();
|
||||
if (mappingData != null) {
|
||||
if (mappingData.getItemMappings() != null) {
|
||||
item.setIdentifier(mappingData.getOldItemId(item.identifier()));
|
||||
}
|
||||
if (mappingData.getDataComponentSerializerMappings() != null) {
|
||||
item.structuredData().setIdLookup(protocol, true);
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.template.protocols.rewriter;
|
||||
|
||||
import com.viaversion.viaversion.api.type.Type;
|
||||
import com.viaversion.viaversion.api.type.types.chunk.ChunkType1_20_2;
|
||||
import com.viaversion.viaversion.api.type.types.version.Types1_20_5;
|
||||
import com.viaversion.viaversion.protocols.protocol1_20_3to1_20_2.rewriter.RecipeRewriter1_20_3;
|
||||
@ -26,13 +25,13 @@ import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.Clientb
|
||||
import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ServerboundPacket1_20_5;
|
||||
import com.viaversion.viaversion.protocols.protocol1_20_5to1_20_3.packet.ServerboundPackets1_20_5;
|
||||
import com.viaversion.viaversion.rewriter.BlockRewriter;
|
||||
import com.viaversion.viaversion.rewriter.ItemRewriter;
|
||||
import com.viaversion.viaversion.rewriter.StructuredItemRewriter;
|
||||
import com.viaversion.viaversion.template.protocols.Protocol1_99To_98;
|
||||
|
||||
// To replace if needed:
|
||||
// ChunkType1_20_2
|
||||
// RecipeRewriter1_20_3
|
||||
public final class BlockItemPacketRewriter1_99 extends ItemRewriter<ClientboundPacket1_20_5, ServerboundPacket1_20_5, Protocol1_99To_98> {
|
||||
public final class BlockItemPacketRewriter1_99 extends StructuredItemRewriter<ClientboundPacket1_20_5, ServerboundPacket1_20_5, Protocol1_99To_98> {
|
||||
|
||||
public BlockItemPacketRewriter1_99(final Protocol1_99To_98 protocol) {
|
||||
super(protocol, /*TypesOLD.ITEM, TypesOLD.ITEM_ARRAY, */Types1_20_5.ITEM, Types1_20_5.ITEM_ARRAY);
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren