Code/net/minecraft/network/syncher/SynchedEntityData.java

245 lines
9.1 KiB
Java

package net.minecraft.network.syncher;
import com.mojang.logging.LogUtils;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.EncoderException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import javax.annotation.Nullable;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.util.ClassTreeIdRegistry;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
public class SynchedEntityData {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int MAX_ID_VALUE = 254;
static final ClassTreeIdRegistry ID_REGISTRY = new ClassTreeIdRegistry();
private final SyncedDataHolder entity;
private final SynchedEntityData.DataItem<?>[] itemsById;
private boolean isDirty;
SynchedEntityData(SyncedDataHolder p_334075_, SynchedEntityData.DataItem<?>[] p_331536_) {
this.entity = p_334075_;
this.itemsById = p_331536_;
}
public static <T> EntityDataAccessor<T> defineId(Class<? extends SyncedDataHolder> p_135354_, EntityDataSerializer<T> p_135355_) {
if (LOGGER.isDebugEnabled()) {
try {
Class<?> oclass = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
if (!oclass.equals(p_135354_)) {
LOGGER.debug("defineId called for: {} from {}", p_135354_, oclass, new RuntimeException());
}
} catch (ClassNotFoundException classnotfoundexception) {
}
}
int i = ID_REGISTRY.define(p_135354_);
if (i > 254) {
throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is 254)");
} else {
return p_135355_.createAccessor(i);
}
}
private <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> p_135380_) {
return (SynchedEntityData.DataItem<T>)this.itemsById[p_135380_.id()];
}
public <T> T get(EntityDataAccessor<T> p_135371_) {
return this.getItem(p_135371_).getValue();
}
public <T> void set(EntityDataAccessor<T> p_135382_, T p_135383_) {
this.set(p_135382_, p_135383_, false);
}
public <T> void set(EntityDataAccessor<T> p_276368_, T p_276363_, boolean p_276370_) {
SynchedEntityData.DataItem<T> dataitem = this.getItem(p_276368_);
if (p_276370_ || ObjectUtils.notEqual(p_276363_, dataitem.getValue())) {
dataitem.setValue(p_276363_);
this.entity.onSyncedDataUpdated(p_276368_);
dataitem.setDirty(true);
this.isDirty = true;
}
}
public boolean isDirty() {
return this.isDirty;
}
@Nullable
public List<SynchedEntityData.DataValue<?>> packDirty() {
if (!this.isDirty) {
return null;
} else {
this.isDirty = false;
List<SynchedEntityData.DataValue<?>> list = new ArrayList<>();
for (SynchedEntityData.DataItem<?> dataitem : this.itemsById) {
if (dataitem.isDirty()) {
dataitem.setDirty(false);
list.add(dataitem.value());
}
}
return list;
}
}
@Nullable
public List<SynchedEntityData.DataValue<?>> getNonDefaultValues() {
List<SynchedEntityData.DataValue<?>> list = null;
for (SynchedEntityData.DataItem<?> dataitem : this.itemsById) {
if (!dataitem.isSetToDefault()) {
if (list == null) {
list = new ArrayList<>();
}
list.add(dataitem.value());
}
}
return list;
}
public void assignValues(List<SynchedEntityData.DataValue<?>> p_135357_) {
for (SynchedEntityData.DataValue<?> datavalue : p_135357_) {
SynchedEntityData.DataItem<?> dataitem = this.itemsById[datavalue.id];
this.assignValue(dataitem, datavalue);
this.entity.onSyncedDataUpdated(dataitem.getAccessor());
}
this.entity.onSyncedDataUpdated(p_135357_);
}
private <T> void assignValue(SynchedEntityData.DataItem<T> p_135376_, SynchedEntityData.DataValue<?> p_254484_) {
if (!Objects.equals(p_254484_.serializer(), p_135376_.accessor.serializer())) {
throw new IllegalStateException(
String.format(
Locale.ROOT,
"Invalid entity data item type for field %d on entity %s: old=%s(%s), new=%s(%s)",
p_135376_.accessor.id(),
this.entity,
p_135376_.value,
p_135376_.value.getClass(),
p_254484_.value,
p_254484_.value.getClass()
)
);
} else {
p_135376_.setValue((T)p_254484_.value);
}
}
public static class Builder {
private final SyncedDataHolder entity;
private final SynchedEntityData.DataItem<?>[] itemsById;
public Builder(SyncedDataHolder p_334752_) {
this.entity = p_334752_;
this.itemsById = new SynchedEntityData.DataItem[SynchedEntityData.ID_REGISTRY.getCount(p_334752_.getClass())];
}
public <T> SynchedEntityData.Builder define(EntityDataAccessor<T> p_329741_, T p_330016_) {
int i = p_329741_.id();
if (i > this.itemsById.length) {
throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is " + this.itemsById.length + ")");
} else if (this.itemsById[i] != null) {
throw new IllegalArgumentException("Duplicate id value for " + i + "!");
} else if (EntityDataSerializers.getSerializedId(p_329741_.serializer()) < 0) {
throw new IllegalArgumentException("Unregistered serializer " + p_329741_.serializer() + " for " + i + "!");
} else {
this.itemsById[p_329741_.id()] = new SynchedEntityData.DataItem<>(p_329741_, p_330016_);
return this;
}
}
public SynchedEntityData build() {
for (int i = 0; i < this.itemsById.length; i++) {
if (this.itemsById[i] == null) {
throw new IllegalStateException("Entity " + this.entity.getClass() + " has not defined synched data value " + i);
}
}
return new SynchedEntityData(this.entity, this.itemsById);
}
}
public static class DataItem<T> {
final EntityDataAccessor<T> accessor;
T value;
private final T initialValue;
private boolean dirty;
public DataItem(EntityDataAccessor<T> p_135394_, T p_135395_) {
this.accessor = p_135394_;
this.initialValue = p_135395_;
this.value = p_135395_;
}
public EntityDataAccessor<T> getAccessor() {
return this.accessor;
}
public void setValue(T p_135398_) {
this.value = p_135398_;
}
public T getValue() {
return this.value;
}
public boolean isDirty() {
return this.dirty;
}
public void setDirty(boolean p_135402_) {
this.dirty = p_135402_;
}
public boolean isSetToDefault() {
return this.initialValue.equals(this.value);
}
public SynchedEntityData.DataValue<T> value() {
return SynchedEntityData.DataValue.create(this.accessor, this.value);
}
}
public record DataValue<T>(int id, EntityDataSerializer<T> serializer, T value) {
public static <T> SynchedEntityData.DataValue<T> create(EntityDataAccessor<T> p_254543_, T p_254138_) {
EntityDataSerializer<T> entitydataserializer = p_254543_.serializer();
return new SynchedEntityData.DataValue<>(p_254543_.id(), entitydataserializer, entitydataserializer.copy(p_254138_));
}
public void write(RegistryFriendlyByteBuf p_328126_) {
int i = EntityDataSerializers.getSerializedId(this.serializer);
if (i < 0) {
throw new EncoderException("Unknown serializer type " + this.serializer);
} else {
p_328126_.writeByte(this.id);
p_328126_.writeVarInt(i);
this.serializer.codec().encode(p_328126_, this.value);
}
}
public static SynchedEntityData.DataValue<?> read(RegistryFriendlyByteBuf p_335154_, int p_254356_) {
int i = p_335154_.readVarInt();
EntityDataSerializer<?> entitydataserializer = EntityDataSerializers.getSerializer(i);
if (entitydataserializer == null) {
throw new DecoderException("Unknown serializer type " + i);
} else {
return read(p_335154_, p_254356_, entitydataserializer);
}
}
private static <T> SynchedEntityData.DataValue<T> read(RegistryFriendlyByteBuf p_333448_, int p_253899_, EntityDataSerializer<T> p_254222_) {
return new SynchedEntityData.DataValue<>(p_253899_, p_254222_, p_254222_.codec().decode(p_333448_));
}
}
}