package net.minecraft.server;
import com.google.common.collect.Lists;
import com.koloboke.collect.map.hash.HashObjIntMaps;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.EncoderException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.annotation.Nullable;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; // Paper
import org.apache.commons.lang3.ObjectUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class DataWatcher {
private static final Logger a = LogManager.getLogger();
private static final Map<Class<? extends Entity>, Integer> b = HashObjIntMaps.newMutableMap();
private final Entity c;
private final Map<Integer, DataWatcher.Item<?>> d = new Int2ObjectOpenHashMap<>(); // Paper
private final ReadWriteLock e = new ReentrantReadWriteLock();
private boolean f = true;
private boolean g;
public DataWatcher(Entity entity) {
this.c = entity;
}
public static <T> DataWatcherObject<T> a(Class<? extends Entity> oclass, DataWatcherSerializer<T> datawatcherserializer) {
if (DataWatcher.a.isDebugEnabled()) {
try {
Class oclass1 = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
if (!oclass1.equals(oclass)) {
DataWatcher.a.debug("defineId called for: {} from {}", new Object[] { oclass, oclass1, new RuntimeException()});
}
} catch (ClassNotFoundException classnotfoundexception) {
;
}
}
int i;
if (DataWatcher.b.containsKey(oclass)) {
i = DataWatcher.b.get(oclass).intValue() + 1;
} else {
int j = 0;
Class oclass2 = oclass;
while (oclass2 != Entity.class) {
oclass2 = oclass2.getSuperclass();
if (DataWatcher.b.containsKey(oclass2)) {
j = DataWatcher.b.get(oclass2).intValue() + 1;
break;
}
}
i = j;
}
if (i > 254) {
throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is " + 254 + ")");
} else {
DataWatcher.b.put(oclass, Integer.valueOf(i));
return datawatcherserializer.a(i);
}
}
public <T> void register(DataWatcherObject<T> datawatcherobject, Object t0) { // CraftBukkit T -> Object
int i = datawatcherobject.a();
if (i > 254) {
throw new IllegalArgumentException("Data value id is too big with " + i + "! (Max is " + 254 + ")");
} else if (this.d.containsKey(Integer.valueOf(i))) {
throw new IllegalArgumentException("Duplicate id value for " + i + "!");
} else if (DataWatcherRegistry.b(datawatcherobject.b()) < 0) {
throw new IllegalArgumentException("Unregistered serializer " + datawatcherobject.b() + " for " + i + "!");
} else {
this.registerObject(datawatcherobject, t0);
}
}
private <T> void registerObject(DataWatcherObject<T> datawatcherobject, Object t0) { // CraftBukkit Object
DataWatcher.Item datawatcher_item = new DataWatcher.Item(datawatcherobject, t0);
this.e.writeLock().lock();
this.d.put(Integer.valueOf(datawatcherobject.a()), datawatcher_item);
this.f = false;
this.e.writeLock().unlock();
}
private <T> DataWatcher.Item<T> c(DataWatcherObject<T> datawatcherobject) {
this.e.readLock().lock();
DataWatcher.Item datawatcher_item;
try {
datawatcher_item = this.d.get(Integer.valueOf(datawatcherobject.a()));
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.a(throwable, "Getting synched entity data");
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Synched entity data");
crashreportsystemdetails.a("Data ID", datawatcherobject);
throw new ReportedException(crashreport);
}
this.e.readLock().unlock();
return datawatcher_item;
}
public <T> T get(DataWatcherObject<T> datawatcherobject) {
return this.c(datawatcherobject).b();
}
public <T> void set(DataWatcherObject<T> datawatcherobject, T t0) {
DataWatcher.Item datawatcher_item = this.c(datawatcherobject);
if (ObjectUtils.notEqual(t0, datawatcher_item.b())) {
datawatcher_item.a(t0);
this.c.a(datawatcherobject);
datawatcher_item.a(true);
this.g = true;
}
}
public <T> void markDirty(DataWatcherObject<T> datawatcherobject) {
this.c(datawatcherobject).c = true;
this.g = true;
}
public boolean a() {
return this.g;
}
public static void a(List<DataWatcher.Item<?>> list, PacketDataSerializer packetdataserializer) throws IOException {
if (list != null) {
int i = 0;
for (int j = list.size(); i < j; ++i) {
DataWatcher.Item datawatcher_item = list.get(i);
a(packetdataserializer, datawatcher_item);
}
}
packetdataserializer.writeByte(255);
}
@Nullable
public List<DataWatcher.Item<?>> b() {
ArrayList arraylist = null;
if (this.g) {
this.e.readLock().lock();
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
DataWatcher.Item datawatcher_item = (DataWatcher.Item) iterator.next();
if (datawatcher_item.c()) {
datawatcher_item.a(false);
if (arraylist == null) {
arraylist = Lists.newArrayList();
}
arraylist.add(datawatcher_item);
}
}
this.e.readLock().unlock();
}
this.g = false;
return arraylist;
}
public void a(PacketDataSerializer packetdataserializer) throws IOException {
this.e.readLock().lock();
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
DataWatcher.Item datawatcher_item = (DataWatcher.Item) iterator.next();
a(packetdataserializer, datawatcher_item);
}
this.e.readLock().unlock();
packetdataserializer.writeByte(255);
}
@Nullable
public List<DataWatcher.Item<?>> c() {
ArrayList arraylist = null;
this.e.readLock().lock();
DataWatcher.Item datawatcher_item;
for (Iterator iterator = this.d.values().iterator(); iterator.hasNext(); arraylist.add(datawatcher_item)) {
datawatcher_item = (DataWatcher.Item) iterator.next();
if (arraylist == null) {
arraylist = Lists.newArrayList();
}
}
this.e.readLock().unlock();
return arraylist;
}
private static <T> void a(PacketDataSerializer packetdataserializer, DataWatcher.Item<T> datawatcher_item) throws IOException {
DataWatcherObject datawatcherobject = datawatcher_item.a();
int i = DataWatcherRegistry.b(datawatcherobject.b());
if (i < 0) {
throw new EncoderException("Unknown serializer type " + datawatcherobject.b());
} else {
packetdataserializer.writeByte(datawatcherobject.a());
packetdataserializer.d(i);
datawatcherobject.b().a(packetdataserializer, datawatcher_item.b());
}
}
@Nullable
public static List<DataWatcher.Item<?>> b(PacketDataSerializer packetdataserializer) throws IOException {
ArrayList arraylist = null;
short short0;
while ((short0 = packetdataserializer.readUnsignedByte()) != 255) {
if (arraylist == null) {
arraylist = Lists.newArrayList();
}
int i = packetdataserializer.g();
DataWatcherSerializer datawatcherserializer = DataWatcherRegistry.a(i);
if (datawatcherserializer == null) {
throw new DecoderException("Unknown serializer type " + i);
}
arraylist.add(new DataWatcher.Item(datawatcherserializer.a(short0), datawatcherserializer.a(packetdataserializer)));
}
return arraylist;
}
public boolean d() {
return this.f;
}
public void e() {
this.g = false;
this.e.readLock().lock();
Iterator iterator = this.d.values().iterator();
while (iterator.hasNext()) {
DataWatcher.Item datawatcher_item = (DataWatcher.Item) iterator.next();
datawatcher_item.a(false);
}
this.e.readLock().unlock();
}
public static class Item<T> {
private final DataWatcherObject<T> a;
private T b;
private boolean c;
public Item(DataWatcherObject<T> datawatcherobject, T t0) {
this.a = datawatcherobject;
this.b = t0;
this.c = true;
}
public DataWatcherObject<T> a() {
return this.a;
}
public void a(T t0) {
this.b = t0;
}
public T b() {
return this.b;
}
public boolean c() {
return this.c;
}
public void a(boolean flag) {
this.c = flag;
}
}
}