mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2024-11-29 13:36:16 +01:00
Make metadata (almost) fail-safe
This could mean life and death, see `new Metadata(17, MetaType1_14.Float, event.meta()).value()` vs. `new Metadata(17, MetaType1_14.Float, event.meta().value())`
This commit is contained in:
parent
a6b4b16fd3
commit
57769c5671
@ -22,6 +22,9 @@
|
||||
*/
|
||||
package com.viaversion.viaversion.api.minecraft.metadata;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class Metadata {
|
||||
@ -29,10 +32,20 @@ public final class Metadata {
|
||||
private MetaType metaType;
|
||||
private Object value;
|
||||
|
||||
public Metadata(int id, MetaType metaType, Object value) {
|
||||
/**
|
||||
* Creates a new metadata instance.
|
||||
*
|
||||
* @param id metadata index
|
||||
* @param metaType metadata type
|
||||
* @param value value if present
|
||||
* @throws NullPointerException if the given metaType is null
|
||||
* @throws IllegalArgumentException if the value and metaType are incompatible
|
||||
*/
|
||||
public Metadata(int id, MetaType metaType, @Nullable Object value) {
|
||||
Preconditions.checkNotNull(metaType);
|
||||
this.id = id;
|
||||
this.metaType = metaType;
|
||||
this.value = value;
|
||||
this.value = checkValue(value);
|
||||
}
|
||||
|
||||
public int id() {
|
||||
@ -47,7 +60,14 @@ public final class Metadata {
|
||||
return metaType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the metadata type.
|
||||
* Update the value with {@link #setValue(Object)} in case value and type are no longer compatible.
|
||||
*
|
||||
* @param metaType metadata type
|
||||
*/
|
||||
public void setMetaType(MetaType metaType) {
|
||||
Preconditions.checkNotNull(metaType);
|
||||
this.metaType = metaType;
|
||||
}
|
||||
|
||||
@ -55,12 +75,26 @@ public final class Metadata {
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
public @Nullable Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
/**
|
||||
* Sets the metadata value.
|
||||
* Always call {@link #setMetaType(MetaType)} first if the output type changes.
|
||||
*
|
||||
* @param value value
|
||||
* @throws IllegalArgumentException if the value and metaType are incompatible
|
||||
*/
|
||||
public void setValue(@Nullable Object value) {
|
||||
this.value = checkValue(value);
|
||||
}
|
||||
|
||||
private Object checkValue(Object value) {
|
||||
if (value != null && !metaType.type().getOutputClass().isAssignableFrom(value.getClass())) {
|
||||
throw new IllegalArgumentException("Metadata value and metaType are incompatible. Type=" + metaType + ", value=" + value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +46,7 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
||||
implements Protocol<C1, C2, S1, S2> {
|
||||
private final Map<Packet, ProtocolPacket> serverbound = new HashMap<>();
|
||||
private final Map<Packet, ProtocolPacket> clientbound = new HashMap<>();
|
||||
private final Map<Class, Object> storedObjects = new HashMap<>(); // currently only used for MetadataRewriters
|
||||
private final Map<Class<?>, Object> storedObjects = new HashMap<>(); // currently only used for MetadataRewriters
|
||||
protected final Class<C1> oldClientboundPacketEnum;
|
||||
protected final Class<C2> newClientboundPacketEnum;
|
||||
protected final Class<S1> oldServerboundPacketEnum;
|
||||
|
@ -139,14 +139,14 @@ public class MetadataRewriter1_14To1_13_2 extends EntityRewriter<Protocol1_14To1
|
||||
} else if (type.is(Entity1_14Types.VILLAGER)) {
|
||||
if (metadata.id() == 15) {
|
||||
// plains
|
||||
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
||||
metadata.setMetaType(MetaType1_14.VillagerData);
|
||||
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
||||
}
|
||||
} else if (type.is(Entity1_14Types.ZOMBIE_VILLAGER)) {
|
||||
if (metadata.id() == 18) {
|
||||
// plains
|
||||
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
||||
metadata.setMetaType(MetaType1_14.VillagerData);
|
||||
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
||||
}
|
||||
} else if (type.isOrHasParent(Entity1_14Types.ABSTRACT_ARROW)) {
|
||||
if (metadata.id() >= 9) { // New piercing
|
||||
@ -154,9 +154,10 @@ public class MetadataRewriter1_14To1_13_2 extends EntityRewriter<Protocol1_14To1
|
||||
}
|
||||
} else if (type.is(Entity1_14Types.FIREWORK_ROCKET)) {
|
||||
if (metadata.id() == 8) {
|
||||
if (metadata.getValue().equals(0))
|
||||
metadata.setValue(null); // https://bugs.mojang.com/browse/MC-111480
|
||||
metadata.setMetaType(MetaType1_14.OptVarInt);
|
||||
if (metadata.getValue().equals(0)) {
|
||||
metadata.setValue(null); // https://bugs.mojang.com/browse/MC-111480
|
||||
}
|
||||
}
|
||||
} else if (type.isOrHasParent(Entity1_14Types.ABSTRACT_SKELETON)) {
|
||||
if (metadata.id() == 14) {
|
||||
|
Loading…
Reference in New Issue
Block a user