321 lines
10 KiB
Java
321 lines
10 KiB
Java
package net.minecraft.server;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
import com.koloboke.collect.map.hash.HashObjIntMap;
|
|
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.ConcurrentHashMap;
|
|
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(255); private static final HashObjIntMap<Class<? extends Entity>> entityTypeToIdMap() { return (HashObjIntMap<Class<? extends Entity>>) b; }// Akarin
|
|
private final Entity c;
|
|
private final Map<Integer, DataWatcher.Item<?>> d = new ConcurrentHashMap<Integer, DataWatcher.Item<?>>(255); // Paper // Akarin
|
|
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 {}", oclass, oclass1, new RuntimeException());
|
|
}
|
|
} catch (ClassNotFoundException classnotfoundexception) {
|
|
;
|
|
}
|
|
}
|
|
|
|
// Akarin start
|
|
int i = entityTypeToIdMap().getOrDefault(oclass, -1);
|
|
|
|
if (i != -1) {
|
|
i = i + 1;
|
|
// Akarin end
|
|
} else {
|
|
int j = 0;
|
|
Class oclass2 = oclass;
|
|
|
|
while (oclass2 != Entity.class) {
|
|
oclass2 = oclass2.getSuperclass();
|
|
// Akarin start
|
|
int superId = entityTypeToIdMap().getOrDefault(oclass2, -1);
|
|
if (superId != -1) {
|
|
j = superId + 1;
|
|
// Akarin end
|
|
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, i);
|
|
return datawatcherserializer.a(i);
|
|
}
|
|
}
|
|
|
|
public <T> void register(DataWatcherObject<T> datawatcherobject, T t0) {
|
|
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(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, T t0) {
|
|
DataWatcher.Item<T> datawatcher_item = new DataWatcher.Item<>(datawatcherobject, t0);
|
|
|
|
//this.e.writeLock().lock(); // Akarin
|
|
this.d.put(datawatcherobject.a(), datawatcher_item);
|
|
this.f = false;
|
|
//this.e.writeLock().unlock(); // Akarin
|
|
}
|
|
|
|
private <T> DataWatcher.Item<T> b(DataWatcherObject<T> datawatcherobject) {
|
|
//this.e.readLock().lock(); // Akarin
|
|
|
|
DataWatcher.Item datawatcher_item;
|
|
|
|
try {
|
|
datawatcher_item = (DataWatcher.Item) this.d.get(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", (Object) datawatcherobject);
|
|
throw new ReportedException(crashreport);
|
|
}
|
|
|
|
//this.e.readLock().unlock(); // Akarin
|
|
return datawatcher_item;
|
|
}
|
|
|
|
public <T> T get(DataWatcherObject<T> datawatcherobject) {
|
|
return this.b(datawatcherobject).b();
|
|
}
|
|
|
|
public <T> void set(DataWatcherObject<T> datawatcherobject, T t0) {
|
|
DataWatcher.Item<T> datawatcher_item = this.b(datawatcherobject);
|
|
|
|
if (ObjectUtils.notEqual(t0, datawatcher_item.b())) {
|
|
datawatcher_item.a(t0);
|
|
this.c.a(datawatcherobject);
|
|
datawatcher_item.a(true);
|
|
this.g = true;
|
|
}
|
|
|
|
}
|
|
|
|
// CraftBukkit start - add method from above
|
|
public <T> void markDirty(DataWatcherObject<T> datawatcherobject) {
|
|
this.b(datawatcherobject).a(true);
|
|
this.g = true;
|
|
}
|
|
// CraftBukkit end
|
|
|
|
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) {
|
|
a(packetdataserializer, (DataWatcher.Item) list.get(i));
|
|
}
|
|
}
|
|
|
|
packetdataserializer.writeByte(255);
|
|
}
|
|
|
|
@Nullable
|
|
public List<DataWatcher.Item<?>> b() {
|
|
List<DataWatcher.Item<?>> list = null;
|
|
|
|
if (this.g) {
|
|
//this.e.readLock().lock(); // Akarin
|
|
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 (list == null) {
|
|
list = Lists.newArrayList();
|
|
}
|
|
|
|
list.add(datawatcher_item.d());
|
|
}
|
|
}
|
|
|
|
//this.e.readLock().unlock(); // Akarin
|
|
}
|
|
|
|
this.g = false;
|
|
return list;
|
|
}
|
|
|
|
public void a(PacketDataSerializer packetdataserializer) throws IOException {
|
|
//this.e.readLock().lock(); // Akarin
|
|
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(); // Akarin
|
|
packetdataserializer.writeByte(255);
|
|
}
|
|
|
|
@Nullable
|
|
public List<DataWatcher.Item<?>> c() {
|
|
List<DataWatcher.Item<?>> list = null;
|
|
|
|
//this.e.readLock().lock(); // Akarin
|
|
|
|
DataWatcher.Item datawatcher_item;
|
|
|
|
for (Iterator iterator = this.d.values().iterator(); iterator.hasNext(); list.add(datawatcher_item.d())) {
|
|
datawatcher_item = (DataWatcher.Item) iterator.next();
|
|
if (list == null) {
|
|
list = Lists.newArrayList();
|
|
}
|
|
}
|
|
|
|
//this.e.readLock().unlock(); // Akarin
|
|
return list;
|
|
}
|
|
|
|
private static <T> void a(PacketDataSerializer packetdataserializer, DataWatcher.Item<T> datawatcher_item) throws IOException {
|
|
DataWatcherObject<T> 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(a(packetdataserializer, short0, datawatcherserializer));
|
|
}
|
|
|
|
return arraylist;
|
|
}
|
|
|
|
private static <T> DataWatcher.Item<T> a(PacketDataSerializer packetdataserializer, int i, DataWatcherSerializer<T> datawatcherserializer) {
|
|
return new DataWatcher.Item<>(datawatcherserializer.a(i), datawatcherserializer.a(packetdataserializer));
|
|
}
|
|
|
|
public boolean d() {
|
|
return this.f;
|
|
}
|
|
|
|
public void e() {
|
|
this.g = false;
|
|
//this.e.readLock().lock(); // Akarin
|
|
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(); // Akarin
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
public DataWatcher.Item<T> d() {
|
|
return new DataWatcher.Item<>(this.a, this.a.b().a(this.b));
|
|
}
|
|
}
|
|
}
|