From 57769c5671a8004f6880cab1d552bde54d5b1d87 Mon Sep 17 00:00:00 2001 From: KennyTV Date: Tue, 25 May 2021 16:27:46 +0200 Subject: [PATCH] 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())` --- .../api/minecraft/metadata/Metadata.java | 44 ++++++++++++++++--- .../api/protocol/AbstractProtocol.java | 2 +- .../MetadataRewriter1_14To1_13_2.java | 9 ++-- 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/api/src/main/java/com/viaversion/viaversion/api/minecraft/metadata/Metadata.java b/api/src/main/java/com/viaversion/viaversion/api/minecraft/metadata/Metadata.java index e6cd6c8ec..69e8f393b 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/minecraft/metadata/Metadata.java +++ b/api/src/main/java/com/viaversion/viaversion/api/minecraft/metadata/Metadata.java @@ -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 diff --git a/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java b/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java index 06d68a933..ede6f7448 100644 --- a/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java +++ b/api/src/main/java/com/viaversion/viaversion/api/protocol/AbstractProtocol.java @@ -46,7 +46,7 @@ public abstract class AbstractProtocol { private final Map serverbound = new HashMap<>(); private final Map clientbound = new HashMap<>(); - private final Map storedObjects = new HashMap<>(); // currently only used for MetadataRewriters + private final Map, Object> storedObjects = new HashMap<>(); // currently only used for MetadataRewriters protected final Class oldClientboundPacketEnum; protected final Class newClientboundPacketEnum; protected final Class oldServerboundPacketEnum; diff --git a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/metadata/MetadataRewriter1_14To1_13_2.java b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/metadata/MetadataRewriter1_14To1_13_2.java index f400deeac..5aab9e90c 100644 --- a/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/metadata/MetadataRewriter1_14To1_13_2.java +++ b/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_14to1_13_2/metadata/MetadataRewriter1_14To1_13_2.java @@ -139,14 +139,14 @@ public class MetadataRewriter1_14To1_13_2 extends EntityRewriter= 9) { // New piercing @@ -154,9 +154,10 @@ public class MetadataRewriter1_14To1_13_2 extends EntityRewriter