Yatopia/patches/server/0026-lithium-MixinDataWatcher.patch
Ivan Pekov 5620825b39
Upstream update & more
Dropped hopper optimizations patch by tr7zw. Sorry buddy, but the patch was making more
problems than it was solving. By no means this is an unneded patch, we will reimplement
it in the future the way it should've been implemented. Fixes #148
2020-08-26 09:17:38 +03: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-MixinDataWatcher
Original code by JellySquid, licensed under GNU Lesser General Public License v3.0
you can find the original code on https://github.com/jellysquid3/lithium-fabric/tree/1.16.x/fabric (Yarn mappings)
Co-authored-by: tr7zw <tr7zw@live.de>
diff --git a/src/main/java/net/minecraft/server/DataWatcher.java b/src/main/java/net/minecraft/server/DataWatcher.java
index e69093b411f76ea4090789576f8fb6635bd02ca5..4a14431b198c227eb6f0f68eaac14f5c09fc3036 100644
--- a/src/main/java/net/minecraft/server/DataWatcher.java
+++ b/src/main/java/net/minecraft/server/DataWatcher.java
@@ -27,6 +27,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;
}
@@ -91,7 +162,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
}
@@ -122,7 +194,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) {