Mirror von
https://github.com/ViaVersion/ViaVersion.git
synchronisiert 2024-12-28 09:00:09 +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())`
Dieser Commit ist enthalten in:
Ursprung
a6b4b16fd3
Commit
57769c5671
@ -22,6 +22,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.viaversion.viaversion.api.minecraft.metadata;
|
package com.viaversion.viaversion.api.minecraft.metadata;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public final class Metadata {
|
public final class Metadata {
|
||||||
@ -29,10 +32,20 @@ public final class Metadata {
|
|||||||
private MetaType metaType;
|
private MetaType metaType;
|
||||||
private Object value;
|
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.id = id;
|
||||||
this.metaType = metaType;
|
this.metaType = metaType;
|
||||||
this.value = value;
|
this.value = checkValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int id() {
|
public int id() {
|
||||||
@ -47,7 +60,14 @@ public final class Metadata {
|
|||||||
return metaType;
|
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) {
|
public void setMetaType(MetaType metaType) {
|
||||||
|
Preconditions.checkNotNull(metaType);
|
||||||
this.metaType = metaType;
|
this.metaType = metaType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,12 +75,26 @@ public final class Metadata {
|
|||||||
return (T) value;
|
return (T) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getValue() {
|
public @Nullable Object getValue() {
|
||||||
return value;
|
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
|
@Override
|
||||||
|
@ -46,7 +46,7 @@ public abstract class AbstractProtocol<C1 extends ClientboundPacketType, C2 exte
|
|||||||
implements Protocol<C1, C2, S1, S2> {
|
implements Protocol<C1, C2, S1, S2> {
|
||||||
private final Map<Packet, ProtocolPacket> serverbound = new HashMap<>();
|
private final Map<Packet, ProtocolPacket> serverbound = new HashMap<>();
|
||||||
private final Map<Packet, ProtocolPacket> clientbound = 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<C1> oldClientboundPacketEnum;
|
||||||
protected final Class<C2> newClientboundPacketEnum;
|
protected final Class<C2> newClientboundPacketEnum;
|
||||||
protected final Class<S1> oldServerboundPacketEnum;
|
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)) {
|
} else if (type.is(Entity1_14Types.VILLAGER)) {
|
||||||
if (metadata.id() == 15) {
|
if (metadata.id() == 15) {
|
||||||
// plains
|
// plains
|
||||||
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
|
||||||
metadata.setMetaType(MetaType1_14.VillagerData);
|
metadata.setMetaType(MetaType1_14.VillagerData);
|
||||||
|
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
||||||
}
|
}
|
||||||
} else if (type.is(Entity1_14Types.ZOMBIE_VILLAGER)) {
|
} else if (type.is(Entity1_14Types.ZOMBIE_VILLAGER)) {
|
||||||
if (metadata.id() == 18) {
|
if (metadata.id() == 18) {
|
||||||
// plains
|
// plains
|
||||||
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
|
||||||
metadata.setMetaType(MetaType1_14.VillagerData);
|
metadata.setMetaType(MetaType1_14.VillagerData);
|
||||||
|
metadata.setValue(new VillagerData(2, getNewProfessionId((int) metadata.getValue()), 0));
|
||||||
}
|
}
|
||||||
} else if (type.isOrHasParent(Entity1_14Types.ABSTRACT_ARROW)) {
|
} else if (type.isOrHasParent(Entity1_14Types.ABSTRACT_ARROW)) {
|
||||||
if (metadata.id() >= 9) { // New piercing
|
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)) {
|
} else if (type.is(Entity1_14Types.FIREWORK_ROCKET)) {
|
||||||
if (metadata.id() == 8) {
|
if (metadata.id() == 8) {
|
||||||
if (metadata.getValue().equals(0))
|
|
||||||
metadata.setValue(null); // https://bugs.mojang.com/browse/MC-111480
|
|
||||||
metadata.setMetaType(MetaType1_14.OptVarInt);
|
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)) {
|
} else if (type.isOrHasParent(Entity1_14Types.ABSTRACT_SKELETON)) {
|
||||||
if (metadata.id() == 14) {
|
if (metadata.id() == 14) {
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren