(Minecraft) SynchedEntityData
unknown
java
a year ago
10 kB
23
Indexable
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.Iterator; 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 trackedEntity, SynchedEntityData.DataItem<?>[] entries) { this.entity = trackedEntity; this.itemsById = entries; } public static <T> EntityDataAccessor<T> defineId(Class<? extends SyncedDataHolder> entityClass, EntityDataSerializer<T> dataHandler) { if (SynchedEntityData.LOGGER.isDebugEnabled()) { try { Class<?> oclass1 = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName()); if (!oclass1.equals(entityClass)) { SynchedEntityData.LOGGER.debug("defineId called for: {} from {}", new Object[]{entityClass, oclass1, new RuntimeException()}); } } catch (ClassNotFoundException classnotfoundexception) { ; } } int i = SynchedEntityData.ID_REGISTRY.define(entityClass); if (i > 254) { throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is 254)"); } else { return dataHandler.createAccessor(i); } } public <T> SynchedEntityData.DataItem<T> getItem(EntityDataAccessor<T> key) { // Paper - public return (SynchedEntityData.DataItem<T>) this.itemsById[key.id()]; // CraftBukkit - decompile error } public <T> T get(EntityDataAccessor<T> data) { return this.getItem(data).getValue(); } public <T> void set(EntityDataAccessor<T> key, T value) { this.set(key, value, false); } public <T> void set(EntityDataAccessor<T> key, T value, boolean force) { SynchedEntityData.DataItem<T> datawatcher_item = this.getItem(key); if (force || ObjectUtils.notEqual(value, datawatcher_item.getValue())) { datawatcher_item.setValue(value); this.entity.onSyncedDataUpdated(key); datawatcher_item.setDirty(true); this.isDirty = true; } } // CraftBukkit start - add method from above public <T> void markDirty(EntityDataAccessor<T> datawatcherobject) { this.getItem(datawatcherobject).setDirty(true); this.isDirty = true; } // CraftBukkit end 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(); SynchedEntityData.DataItem[] adatawatcher_item = this.itemsById; int i = adatawatcher_item.length; for (int j = 0; j < i; ++j) { SynchedEntityData.DataItem<?> datawatcher_item = adatawatcher_item[j]; if (datawatcher_item.isDirty()) { datawatcher_item.setDirty(false); list.add(datawatcher_item.value()); } } return list; } } @Nullable public List<SynchedEntityData.DataValue<?>> getNonDefaultValues() { List<SynchedEntityData.DataValue<?>> list = null; SynchedEntityData.DataItem[] adatawatcher_item = this.itemsById; int i = adatawatcher_item.length; for (int j = 0; j < i; ++j) { SynchedEntityData.DataItem<?> datawatcher_item = adatawatcher_item[j]; if (!datawatcher_item.isSetToDefault()) { if (list == null) { list = new ArrayList(); } list.add(datawatcher_item.value()); } } return list; } public void assignValues(List<SynchedEntityData.DataValue<?>> entries) { Iterator iterator = entries.iterator(); while (iterator.hasNext()) { SynchedEntityData.DataValue<?> datawatcher_c = (SynchedEntityData.DataValue) iterator.next(); SynchedEntityData.DataItem<?> datawatcher_item = this.itemsById[datawatcher_c.id]; this.assignValue(datawatcher_item, datawatcher_c); this.entity.onSyncedDataUpdated(datawatcher_item.getAccessor()); } this.entity.onSyncedDataUpdated(entries); } private <T> void assignValue(SynchedEntityData.DataItem<T> to, SynchedEntityData.DataValue<?> from) { if (!Objects.equals(from.serializer(), to.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)", to.accessor.id(), this.entity, to.value, to.value.getClass(), from.value, from.value.getClass())); } else { to.setValue((T) from.value); // CraftBukkit - decompile error } } // Paper start // We need to pack all as we cannot rely on "non default values" or "dirty" ones. // Because these values can possibly be desynced on the client. @Nullable public List<SynchedEntityData.DataValue<?>> packAll() { final List<SynchedEntityData.DataValue<?>> list = new ArrayList<>(); for (final DataItem<?> dataItem : this.itemsById) { list.add(dataItem.value()); } return list; } // Paper end public static class DataItem<T> { final EntityDataAccessor<T> accessor; T value; private final T initialValue; private boolean dirty; public DataItem(EntityDataAccessor<T> data, T value) { this.accessor = data; this.initialValue = value; this.value = value; } public EntityDataAccessor<T> getAccessor() { return this.accessor; } public void setValue(T value) { this.value = value; } public T getValue() { return this.value; } public boolean isDirty() { return this.dirty; } public void setDirty(boolean dirty) { this.dirty = dirty; } public boolean isSetToDefault() { return this.initialValue.equals(this.value); } public SynchedEntityData.DataValue<T> value() { return SynchedEntityData.DataValue.create(this.accessor, this.value); } } public static record DataValue<T>(int id, EntityDataSerializer<T> serializer, T value) { public static <T> SynchedEntityData.DataValue<T> create(EntityDataAccessor<T> data, T value) { EntityDataSerializer<T> datawatcherserializer = data.serializer(); return new SynchedEntityData.DataValue<>(data.id(), datawatcherserializer, datawatcherserializer.copy(value)); } public void write(RegistryFriendlyByteBuf buf) { int i = EntityDataSerializers.getSerializedId(this.serializer); if (i < 0) { throw new EncoderException("Unknown serializer type " + String.valueOf(this.serializer)); } else { buf.writeByte(this.id); buf.writeVarInt(i); this.serializer.codec().encode(buf, this.value); } } public static SynchedEntityData.DataValue<?> read(RegistryFriendlyByteBuf buf, int id) { int j = buf.readVarInt(); EntityDataSerializer<?> datawatcherserializer = EntityDataSerializers.getSerializer(j); if (datawatcherserializer == null) { throw new DecoderException("Unknown serializer type " + j); } else { return read(buf, id, datawatcherserializer); } } private static <T> SynchedEntityData.DataValue<T> read(RegistryFriendlyByteBuf buf, int id, EntityDataSerializer<T> handler) { return new SynchedEntityData.DataValue<>(id, handler, handler.codec().decode(buf)); } } public static class Builder { private final SyncedDataHolder entity; private final SynchedEntityData.DataItem<?>[] itemsById; public Builder(SyncedDataHolder entity) { this.entity = entity; this.itemsById = new SynchedEntityData.DataItem[SynchedEntityData.ID_REGISTRY.getCount(entity.getClass())]; } public <T> SynchedEntityData.Builder define(EntityDataAccessor<T> data, T value) { int i = data.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(data.serializer()) < 0) { String s = String.valueOf(data.serializer()); throw new IllegalArgumentException("Unregistered serializer " + s + " for " + i + "!"); } else { this.itemsById[data.id()] = new SynchedEntityData.DataItem<>(data, value); return this; } } public SynchedEntityData build() { for (int i = 0; i < this.itemsById.length; ++i) { if (this.itemsById[i] == null) { String s = String.valueOf(this.entity.getClass()); throw new IllegalStateException("Entity " + s + " has not defined synched data value " + i); } } return new SynchedEntityData(this.entity, this.itemsById); } } }
Editor is loading...
Leave a Comment