Yatopia/patches/server/0019-lithium-DataTrackerMixin.patch
2021-05-20 12:51:47 -04:00

113 lines
5.0 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: JellySquid <jellysquid+atwork@protonmail.com>
Date: Tue, 4 Aug 2020 21:46:05 +0200
Subject: [PATCH] lithium DataTrackerMixin
Original code by JellySquid, licensed under GNU Lesser General Public License v3.0
you can find the original code on https://github.com/CaffeineMC/lithium-fabric/ (Yarn mappings)
Co-authored-by: tr7zw <tr7zw@live.de>
diff --git a/src/main/java/net/minecraft/network/syncher/DataWatcher.java b/src/main/java/net/minecraft/network/syncher/DataWatcher.java
index bb09b7be91b488ebc336b2b6f5deafc0ccab27a4..c03f1293848192cada5e3a6238f7a5c11cd4ab10 100644
--- a/src/main/java/net/minecraft/network/syncher/DataWatcher.java
+++ b/src/main/java/net/minecraft/network/syncher/DataWatcher.java
@@ -32,6 +32,77 @@ public class DataWatcher {
private boolean f = true;
private boolean g;
+ // Yatopia lithium start
+ private static final int DEFAULT_ENTRY_COUNT = 10, GROW_FACTOR = 8;
+ /** Mirrors the vanilla backing entries map. Each DataWatcher.Item can be accessed in this array through its ID. **/
+ private DataWatcher.Item<?>[] entriesArray = new DataWatcher.Item<?>[DEFAULT_ENTRY_COUNT];
+
+ /**
+ * We redirect the call to add a tracked data to the internal map so we can add it to our new storage structure. This
+ * should only ever occur during entity initialization. Type-erasure is a bit of a pain here since we must redirect
+ * a calls to the generic Map interface.
+ */
+ private Object onAddTrackedDataInsertMap(Int2ObjectOpenHashMap<DataWatcher.Item<?>> map, int keyRaw, DataWatcher.Item<?> valueRaw) {
+ int k = keyRaw;
+ DataWatcher.Item<?> v = (DataWatcher.Item<?>) valueRaw;
+
+ DataWatcher.Item<?>[] storage = this.entriesArray;
+
+ // Check if we need to grow the backing array to accommodate the new key range
+ if (storage.length <= k) {
+ // Grow the array to accommodate 8 entries after this one, but limit it to never be larger
+ // than 256 entries as per the vanilla limit
+ int newSize = Math.min(k + GROW_FACTOR, 256);
+
+ this.entriesArray = storage = java.util.Arrays.copyOf(storage, newSize);
+ }
+
+ // Update the storage
+ storage[k] = v;
+
+ // Ensure that the vanilla backing storage is still updated appropriately
+ return this.entries.put(k, v);
+ }
+
+ /**
+ * @reason Avoid integer boxing/unboxing and use our array-based storage
+ * @author JellySquid
+ */
+ private <T> DataWatcher.Item<T> getEntry(DataWatcherObject<T> data) {
+ try {
+ DataWatcher.Item<?>[] array = this.entriesArray;
+
+ int id = data.a();
+
+ // The vanilla implementation will simply return null if the tracker doesn't contain the specified entry. However,
+ // accessing an array with an invalid pointer will throw a OOB exception, where-as a HashMap would simply
+ // return null. We check this case (which should be free, even if so insignificant, as the subsequent bounds
+ // check will hopefully be eliminated)
+ if (id < 0 || id >= array.length) {
+ return null;
+ }
+
+ // This cast can fail if trying to access a entry which doesn't belong to this tracker, as the ID could
+ // instead point to an entry of a different type. However, that is also vanilla behaviour.
+ // noinspection unchecked
+ return (DataWatcher.Item<T>) array[id];
+ } catch (Throwable cause) {
+ // Move to another method so this function can be in-lined better
+ throw onGetException(cause, data);
+ }
+ }
+
+ private static <T> ReportedException onGetException(Throwable cause, DataWatcherObject<T> data) {
+ CrashReport report = CrashReport.a(cause, "Getting synced entity data");
+
+ CrashReportSystemDetails section = report.a("Synced entity data");
+ section.a("Data ID", data);
+
+ return new ReportedException(report);
+ }
+
+ // Yatopia lithium end
+
public DataWatcher(Entity entity) {
this.entity = entity;
}
@@ -96,7 +167,8 @@ public class DataWatcher {
DataWatcher.Item<T> datawatcher_item = new DataWatcher.Item<>(datawatcherobject, t0);
// this.lock.writeLock().lock(); // Spigot - not required
- this.entries.put(datawatcherobject.a(), datawatcher_item);
+ //this.entries.put(datawatcherobject.a(), datawatcher_item);
+ this.onAddTrackedDataInsertMap(this.entries, datawatcherobject.a(), datawatcher_item); // Yatopia lithium
this.f = false;
// this.lock.writeLock().unlock(); // Spigot - not required
}
@@ -127,7 +199,8 @@ public class DataWatcher {
}
public <T> T get(DataWatcherObject<T> datawatcherobject) {
- return this.b(datawatcherobject).b();
+ return getEntry(datawatcherobject).b(); // Yatopia
+ //return this.b(datawatcherobject).b();
}
public <T> void set(DataWatcherObject<T> datawatcherobject, T t0) {