Yatopia/patches/server/0027-lithium-MixinDataWatcher.patch
budgidiere c09ee99f7e
Hydrinity optimizations & Lithium generation patches & more
Closes #257 

Ports 2 patches from Purpur: Infinity-bow-settings & Allow-infinite-and-mending-enchantments-together
Added an option for infinity with no arrows too.

Option for custom locale has come! You can put a locale.json file in your server folder to change it. 

We've got the finest patches from Hydrinity ( Mykyta approved & allowed ) too.

We have some amazing new options in yatopia.yml, we're gonna have documentation for them soon so stay tuned!
Last but not least, chunk generation patches. We've tested them extensively so no weirdness happens.

Thanks for using Yatopia as your production server software.

Co-authored-by: Ivan Pekov <ivan@mrivanplays.com>
2020-10-27 21:15:13 +02: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) {