mirror of
https://github.com/YatopiaMC/Yatopia.git
synced 2024-12-05 00:53:43 +01:00
645 lines
25 KiB
Diff
645 lines
25 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: JellySquid <jellysquid+atwork@protonmail.com>
|
||
|
Date: Wed, 20 Jan 2021 20:14:55 +0100
|
||
|
Subject: [PATCH] Port hydrogen
|
||
|
|
||
|
|
||
|
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/cache/StatePropertyTableCache.java b/src/main/java/me/jellysquid/mods/lithium/common/cache/StatePropertyTableCache.java
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..dd18bb8b3550d0fe9ba2589151baceb9100ae6f2
|
||
|
--- /dev/null
|
||
|
+++ b/src/main/java/me/jellysquid/mods/lithium/common/cache/StatePropertyTableCache.java
|
||
|
@@ -0,0 +1,38 @@
|
||
|
+package me.jellysquid.mods.lithium.common.cache;
|
||
|
+
|
||
|
+import me.jellysquid.mods.lithium.common.collections.FastImmutableTableCache;
|
||
|
+import net.minecraft.server.Block;
|
||
|
+import net.minecraft.server.Fluid;
|
||
|
+import net.minecraft.server.FluidType;
|
||
|
+import net.minecraft.server.IBlockData;
|
||
|
+import net.minecraft.server.IBlockState;
|
||
|
+
|
||
|
+/**
|
||
|
+ * Many of the column and row key arrays in block state tables will be duplicated, leading to an unnecessary waste of
|
||
|
+ * memory. Since we have very limited options for trying to construct more optimized table types without throwing
|
||
|
+ * maintainability or mod compatibility out the window, this class acts as a dirty way to find and de-duplicate arrays
|
||
|
+ * after we construct our table types.
|
||
|
+ * <p>
|
||
|
+ * While this global cache does not provide the ability to remove or clear entries from it, the reality is that it
|
||
|
+ * shouldn't matter because block state tables are only initialized once and remain loaded for the entire lifetime of
|
||
|
+ * the game. Even in the event of classloader pre-boot shenanigans, we still shouldn't leak memory as our cache will be
|
||
|
+ * dropped along with the rest of the loaded classes when the class loader is reaped.
|
||
|
+ */
|
||
|
+public class StatePropertyTableCache {
|
||
|
+ public static final FastImmutableTableCache<IBlockState<?>, Comparable<?>, IBlockData> BLOCK_STATE_TABLE =
|
||
|
+ new FastImmutableTableCache<>();
|
||
|
+
|
||
|
+ public static final FastImmutableTableCache<IBlockState<?>, Comparable<?>, Fluid> FLUID_STATE_TABLE =
|
||
|
+ new FastImmutableTableCache<>();
|
||
|
+
|
||
|
+ @SuppressWarnings("unchecked")
|
||
|
+ public static <S, O> FastImmutableTableCache<IBlockState<?>, Comparable<?>, S> getTableCache(O owner) {
|
||
|
+ if (owner instanceof Block) {
|
||
|
+ return (FastImmutableTableCache<IBlockState<?>, Comparable<?>, S>) BLOCK_STATE_TABLE;
|
||
|
+ } else if (owner instanceof FluidType) {
|
||
|
+ return (FastImmutableTableCache<IBlockState<?>, Comparable<?>, S>) FLUID_STATE_TABLE;
|
||
|
+ } else {
|
||
|
+ throw new IllegalArgumentException("");
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
\ No newline at end of file
|
||
|
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/collections/FastImmutableTable.java b/src/main/java/me/jellysquid/mods/lithium/common/collections/FastImmutableTable.java
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..9aa45ecdff223258c4f3252a61b9ccbbed6151d2
|
||
|
--- /dev/null
|
||
|
+++ b/src/main/java/me/jellysquid/mods/lithium/common/collections/FastImmutableTable.java
|
||
|
@@ -0,0 +1,227 @@
|
||
|
+package me.jellysquid.mods.lithium.common.collections;
|
||
|
+
|
||
|
+import com.google.common.collect.Table;
|
||
|
+import it.unimi.dsi.fastutil.Hash;
|
||
|
+import it.unimi.dsi.fastutil.HashCommon;
|
||
|
+import org.apache.commons.lang3.ArrayUtils;
|
||
|
+
|
||
|
+import java.util.Collection;
|
||
|
+import java.util.Map;
|
||
|
+import java.util.Set;
|
||
|
+
|
||
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
||
|
+
|
||
|
+public class FastImmutableTable<R, C, V> implements Table<R, C, V> {
|
||
|
+ private R[] rowKeys;
|
||
|
+ private int[] rowIndices;
|
||
|
+ private final int rowMask;
|
||
|
+ private final int rowCount;
|
||
|
+
|
||
|
+ private C[] colKeys;
|
||
|
+ private int[] colIndices;
|
||
|
+ private final int colMask;
|
||
|
+ private final int colCount;
|
||
|
+
|
||
|
+ private V[] values;
|
||
|
+ private final int size;
|
||
|
+
|
||
|
+ @SuppressWarnings("unchecked")
|
||
|
+ public FastImmutableTable(Table<R, C, V> table, FastImmutableTableCache<R, C, V> cache) {
|
||
|
+ if (cache == null) {
|
||
|
+ throw new IllegalArgumentException("Cache must not be null");
|
||
|
+ }
|
||
|
+
|
||
|
+ float loadFactor = Hash.DEFAULT_LOAD_FACTOR;
|
||
|
+
|
||
|
+ Set<R> rowKeySet = table.rowKeySet();
|
||
|
+ Set<C> colKeySet = table.columnKeySet();
|
||
|
+
|
||
|
+ this.rowCount = rowKeySet.size();
|
||
|
+ this.colCount = colKeySet.size();
|
||
|
+
|
||
|
+ int rowN = arraySize(this.rowCount, loadFactor);
|
||
|
+ int colN = arraySize(this.colCount, loadFactor);
|
||
|
+
|
||
|
+ this.rowMask = rowN - 1;
|
||
|
+ this.rowKeys = (R[]) new Object[rowN];
|
||
|
+ this.rowIndices = new int[rowN];
|
||
|
+
|
||
|
+ this.colMask = colN - 1;
|
||
|
+ this.colKeys = (C[]) new Object[colN];
|
||
|
+ this.colIndices = new int[colN];
|
||
|
+
|
||
|
+ this.createIndex(this.colKeys, this.colIndices, this.colMask, colKeySet);
|
||
|
+ this.createIndex(this.rowKeys, this.rowIndices, this.rowMask, rowKeySet);
|
||
|
+
|
||
|
+ this.values = (V[]) new Object[this.rowCount * this.colCount];
|
||
|
+
|
||
|
+ for (Cell<R, C, V> cell : table.cellSet()) {
|
||
|
+ int colIdx = this.getIndex(this.colKeys, this.colIndices, this.colMask, cell.getColumnKey());
|
||
|
+ int rowIdx = this.getIndex(this.rowKeys, this.rowIndices, this.rowMask, cell.getRowKey());
|
||
|
+
|
||
|
+ if (colIdx < 0 || rowIdx < 0) {
|
||
|
+ throw new IllegalStateException("Missing index for " + cell);
|
||
|
+ }
|
||
|
+
|
||
|
+ this.values[this.colCount * rowIdx + colIdx] = cell.getValue();
|
||
|
+ }
|
||
|
+
|
||
|
+ this.size = table.size();
|
||
|
+
|
||
|
+ this.rowKeys = cache.dedupRows(this.rowKeys);
|
||
|
+ this.rowIndices = cache.dedupIndices(this.rowIndices);
|
||
|
+
|
||
|
+ this.colIndices = cache.dedupIndices(this.colIndices);
|
||
|
+ this.colKeys = cache.dedupColumns(this.colKeys);
|
||
|
+
|
||
|
+ this.values = cache.dedupValues(this.values);
|
||
|
+ }
|
||
|
+
|
||
|
+ private <T> void createIndex(T[] keys, int[] indices, int mask, Collection<T> iterable) {
|
||
|
+ int index = 0;
|
||
|
+
|
||
|
+ for (T obj : iterable) {
|
||
|
+ int i = this.find(keys, mask, obj);
|
||
|
+
|
||
|
+ if (i < 0) {
|
||
|
+ int pos = -i - 1;
|
||
|
+
|
||
|
+ keys[pos] = obj;
|
||
|
+ indices[pos] = index++;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ private <T> int getIndex(T[] keys, int[] indices, int mask, T key) {
|
||
|
+ int pos = this.find(keys, mask, key);
|
||
|
+
|
||
|
+ if (pos < 0) {
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+
|
||
|
+ return indices[pos];
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public boolean contains(Object rowKey, Object columnKey) {
|
||
|
+ return this.get(rowKey, columnKey) != null;
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public boolean containsRow(Object rowKey) {
|
||
|
+ return this.find(this.rowKeys, this.rowMask, rowKey) >= 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public boolean containsColumn(Object columnKey) {
|
||
|
+ return this.find(this.colKeys, this.colMask, columnKey) >= 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public boolean containsValue(Object value) {
|
||
|
+ return ArrayUtils.contains(this.values, value);
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public V get(Object rowKey, Object columnKey) {
|
||
|
+ final int row = this.getIndex(this.rowKeys, this.rowIndices, this.rowMask, rowKey);
|
||
|
+ final int col = this.getIndex(this.colKeys, this.colIndices, this.colMask, columnKey);
|
||
|
+
|
||
|
+ if (row < 0 || col < 0) {
|
||
|
+ return null;
|
||
|
+ }
|
||
|
+
|
||
|
+ return this.values[this.colCount * row + col];
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public boolean isEmpty() {
|
||
|
+ return this.size() == 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public int size() {
|
||
|
+ return this.size;
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public void clear() {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public V put(R rowKey, C columnKey, V val) {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ private <T> int find(T[] key, int mask, T value) {
|
||
|
+ T curr;
|
||
|
+ int pos;
|
||
|
+ // The starting point.
|
||
|
+ if ((curr = key[pos = HashCommon.mix(value.hashCode()) & mask]) == null) {
|
||
|
+ return -(pos + 1);
|
||
|
+ }
|
||
|
+ if (value.equals(curr)) {
|
||
|
+ return pos;
|
||
|
+ }
|
||
|
+ // There's always an unused entry.
|
||
|
+ while (true) {
|
||
|
+ if ((curr = key[pos = pos + 1 & mask]) == null) {
|
||
|
+ return -(pos + 1);
|
||
|
+ }
|
||
|
+ if (value.equals(curr)) {
|
||
|
+ return pos;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public V remove(Object rowKey, Object columnKey) {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Map<C, V> row(R rowKey) {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Map<R, V> column(C columnKey) {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Set<Cell<R, C, V>> cellSet() {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Set<R> rowKeySet() {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Set<C> columnKeySet() {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Collection<V> values() {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Map<R, Map<C, V>> rowMap() {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+
|
||
|
+ @Override
|
||
|
+ public Map<C, Map<R, V>> columnMap() {
|
||
|
+ throw new UnsupportedOperationException();
|
||
|
+ }
|
||
|
+}
|
||
|
\ No newline at end of file
|
||
|
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/collections/FastImmutableTableCache.java b/src/main/java/me/jellysquid/mods/lithium/common/collections/FastImmutableTableCache.java
|
||
|
new file mode 100644
|
||
|
index 0000000000000000000000000000000000000000..a5314a0396f4a8f373d855e873820ddddd635a4a
|
||
|
--- /dev/null
|
||
|
+++ b/src/main/java/me/jellysquid/mods/lithium/common/collections/FastImmutableTableCache.java
|
||
|
@@ -0,0 +1,44 @@
|
||
|
+package me.jellysquid.mods.lithium.common.collections;
|
||
|
+
|
||
|
+import it.unimi.dsi.fastutil.Hash;
|
||
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
||
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
||
|
+import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet;
|
||
|
+
|
||
|
+/**
|
||
|
+ * @param <R> The type used by the
|
||
|
+ * @param <C>
|
||
|
+ * @param <V>
|
||
|
+ */
|
||
|
+public class FastImmutableTableCache<R, C, V> {
|
||
|
+ private final ObjectOpenCustomHashSet<R[]> rows;
|
||
|
+ private final ObjectOpenCustomHashSet<C[]> columns;
|
||
|
+ private final ObjectOpenCustomHashSet<V[]> values;
|
||
|
+
|
||
|
+ private final ObjectOpenCustomHashSet<int[]> indices;
|
||
|
+
|
||
|
+ @SuppressWarnings("unchecked")
|
||
|
+ public FastImmutableTableCache() {
|
||
|
+ this.rows = new ObjectOpenCustomHashSet<>((Hash.Strategy<R[]>) ObjectArrays.HASH_STRATEGY);
|
||
|
+ this.columns = new ObjectOpenCustomHashSet<>((Hash.Strategy<C[]>) ObjectArrays.HASH_STRATEGY);
|
||
|
+ this.values = new ObjectOpenCustomHashSet<>((Hash.Strategy<V[]>) ObjectArrays.HASH_STRATEGY);
|
||
|
+
|
||
|
+ this.indices = new ObjectOpenCustomHashSet<>(IntArrays.HASH_STRATEGY);
|
||
|
+ }
|
||
|
+
|
||
|
+ public synchronized V[] dedupValues(V[] values) {
|
||
|
+ return this.values.addOrGet(values);
|
||
|
+ }
|
||
|
+
|
||
|
+ public synchronized R[] dedupRows(R[] rows) {
|
||
|
+ return this.rows.addOrGet(rows);
|
||
|
+ }
|
||
|
+
|
||
|
+ public synchronized C[] dedupColumns(C[] columns) {
|
||
|
+ return this.columns.addOrGet(columns);
|
||
|
+ }
|
||
|
+
|
||
|
+ public synchronized int[] dedupIndices(int[] ints) {
|
||
|
+ return this.indices.addOrGet(ints);
|
||
|
+ }
|
||
|
+}
|
||
|
diff --git a/src/main/java/net/minecraft/server/BiomeStorage.java b/src/main/java/net/minecraft/server/BiomeStorage.java
|
||
|
index b7f5c932197529c0ea045cfe696fd5da1ccc7202..af6245ba0c6b1389703722596ab7aa50deaf9e9f 100644
|
||
|
--- a/src/main/java/net/minecraft/server/BiomeStorage.java
|
||
|
+++ b/src/main/java/net/minecraft/server/BiomeStorage.java
|
||
|
@@ -1,23 +1,32 @@
|
||
|
package net.minecraft.server;
|
||
|
|
||
|
import javax.annotation.Nullable;
|
||
|
+
|
||
|
+import it.unimi.dsi.fastutil.objects.Reference2ShortMap;
|
||
|
+import it.unimi.dsi.fastutil.objects.Reference2ShortOpenHashMap;
|
||
|
import org.apache.logging.log4j.LogManager;
|
||
|
import org.apache.logging.log4j.Logger;
|
||
|
|
||
|
public class BiomeStorage implements BiomeManager.Provider {
|
||
|
|
||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||
|
- private static final int e = (int) Math.round(Math.log(16.0D) / Math.log(2.0D)) - 2;
|
||
|
+ private static final int e = (int) Math.round(Math.log(16.0D) / Math.log(2.0D)) - 2; public static final int HORIZONTAL_SECTION_COUNT = e; // Yatopia - OBFHELPER
|
||
|
private static final int f = (int) Math.round(Math.log(256.0D) / Math.log(2.0D)) - 2;
|
||
|
public static final int a = 1 << BiomeStorage.e + BiomeStorage.e + BiomeStorage.f;
|
||
|
- public static final int b = (1 << BiomeStorage.e) - 1;
|
||
|
- public static final int c = (1 << BiomeStorage.f) - 1;
|
||
|
+ public static final int b = (1 << BiomeStorage.e) - 1; public static final int HORIZONTAL_BIT_MASK = b; // Yatopia - OBFHELPER
|
||
|
+ public static final int c = (1 << BiomeStorage.f) - 1; public static final int VERTICAL_BIT_MASK = c; // Yatopia - OBFHELPER
|
||
|
public final Registry<BiomeBase> registry;
|
||
|
- private final BiomeBase[] h;
|
||
|
+ private BiomeBase[] h; private BiomeBase[] getData() { return h; } // Yatopia - OBFHELPER , remove final
|
||
|
+
|
||
|
+ // Yatopia start - Port hydrogen
|
||
|
+ private BiomeBase[] palette;
|
||
|
+ private DataBits intArray;
|
||
|
+ // Yatopia end
|
||
|
|
||
|
public BiomeStorage(Registry<BiomeBase> registry, BiomeBase[] abiomebase) {
|
||
|
this.registry = registry;
|
||
|
this.h = abiomebase;
|
||
|
+ this.createCompact(); // Yatopia - Port hydrogen
|
||
|
}
|
||
|
|
||
|
private BiomeStorage(Registry<BiomeBase> registry) {
|
||
|
@@ -37,6 +46,7 @@ public class BiomeStorage implements BiomeManager.Provider {
|
||
|
this.h[k] = worldchunkmanager.getBiome(i + l, i1, j + j1);
|
||
|
}
|
||
|
|
||
|
+ this.createCompact(); // Yatopia - Port hydrogen
|
||
|
}
|
||
|
|
||
|
public BiomeStorage(Registry<BiomeBase> registry, ChunkCoordIntPair chunkcoordintpair, WorldChunkManager worldchunkmanager, @Nullable int[] aint) {
|
||
|
@@ -67,9 +77,11 @@ public class BiomeStorage implements BiomeManager.Provider {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ this.createCompact(); // Yatopia - Port hydrogen
|
||
|
}
|
||
|
|
||
|
public int[] a() {
|
||
|
+ /* // Yatopia start - Port hydrogen
|
||
|
int[] aint = new int[this.h.length];
|
||
|
|
||
|
for (int i = 0; i < this.h.length; ++i) {
|
||
|
@@ -77,15 +89,33 @@ public class BiomeStorage implements BiomeManager.Provider {
|
||
|
}
|
||
|
|
||
|
return aint;
|
||
|
+ */
|
||
|
+ int size = this.intArray.getSize();
|
||
|
+ int[] array = new int[size];
|
||
|
+
|
||
|
+ for (int i = 0; i < size; ++i) {
|
||
|
+ array[i] = this.registry.a(this.palette[this.intArray.get(i)]);
|
||
|
+ }
|
||
|
+
|
||
|
+ return array;
|
||
|
+ // Yatopia end
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public BiomeBase getBiome(int i, int j, int k) {
|
||
|
+ /* // Yatopia start - Port hydrogen
|
||
|
int l = i & BiomeStorage.b;
|
||
|
int i1 = MathHelper.clamp(j, 0, BiomeStorage.c);
|
||
|
int j1 = k & BiomeStorage.b;
|
||
|
|
||
|
return this.h[i1 << BiomeStorage.e + BiomeStorage.e | j1 << BiomeStorage.e | l];
|
||
|
+ */
|
||
|
+ int x = i & HORIZONTAL_BIT_MASK;
|
||
|
+ int y = MathHelper.clamp(j, 0, VERTICAL_BIT_MASK);
|
||
|
+ int z = k & HORIZONTAL_BIT_MASK;
|
||
|
+
|
||
|
+ return this.palette[this.intArray.get(y << HORIZONTAL_SECTION_COUNT + HORIZONTAL_SECTION_COUNT | z << HORIZONTAL_SECTION_COUNT | x)];
|
||
|
+ // Yatopia end
|
||
|
}
|
||
|
|
||
|
// CraftBukkit start
|
||
|
@@ -94,7 +124,74 @@ public class BiomeStorage implements BiomeManager.Provider {
|
||
|
int i1 = MathHelper.clamp(j, 0, BiomeStorage.c);
|
||
|
int j1 = k & BiomeStorage.b;
|
||
|
|
||
|
- this.h[i1 << BiomeStorage.e + BiomeStorage.e | j1 << BiomeStorage.e | l] = biome;
|
||
|
+ this.palette[this.intArray.get(l << HORIZONTAL_SECTION_COUNT + HORIZONTAL_SECTION_COUNT | i1 << HORIZONTAL_SECTION_COUNT | j1)] = biome; // Yatopia - Port Hydrogen
|
||
|
}
|
||
|
// CraftBukkit end
|
||
|
+
|
||
|
+
|
||
|
+ // Yatopia Start - Port Hydrogen
|
||
|
+ private void createCompact() {
|
||
|
+ if (this.intArray != null || this.getData()[0] == null) {
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ Reference2ShortOpenHashMap<BiomeBase> paletteTable = this.createPalette();
|
||
|
+ BiomeBase[] paletteIndexed = new BiomeBase[paletteTable.size()];
|
||
|
+
|
||
|
+ for (Reference2ShortMap.Entry<BiomeBase> entry : paletteTable.reference2ShortEntrySet()) {
|
||
|
+ paletteIndexed[entry.getShortValue()] = entry.getKey();
|
||
|
+ }
|
||
|
+
|
||
|
+ int packedIntSize = Math.max(2, MathHelper.e(paletteTable.size()));
|
||
|
+ DataBits integerArray = new DataBits(packedIntSize, a);
|
||
|
+
|
||
|
+ BiomeBase prevBiome = null;
|
||
|
+ short prevId = -1;
|
||
|
+
|
||
|
+ for (int i = 0; i < this.getData().length; i++) {
|
||
|
+ BiomeBase biome = this.getData()[i];
|
||
|
+ short id;
|
||
|
+
|
||
|
+ if (prevBiome == biome) {
|
||
|
+ id = prevId;
|
||
|
+ } else {
|
||
|
+ id = paletteTable.getShort(biome);
|
||
|
+
|
||
|
+ if (id < 0) {
|
||
|
+ throw new IllegalStateException("Palette is missing entry: " + biome);
|
||
|
+ }
|
||
|
+
|
||
|
+ prevId = id;
|
||
|
+ prevBiome = biome;
|
||
|
+ }
|
||
|
+
|
||
|
+ integerArray.set(i, id);
|
||
|
+ }
|
||
|
+
|
||
|
+ this.palette = paletteIndexed;
|
||
|
+ this.intArray = integerArray;
|
||
|
+ this.h = null;
|
||
|
+ }
|
||
|
+
|
||
|
+ private Reference2ShortOpenHashMap<BiomeBase> createPalette() {
|
||
|
+ Reference2ShortOpenHashMap<BiomeBase> map = new Reference2ShortOpenHashMap<>();
|
||
|
+ map.defaultReturnValue(Short.MIN_VALUE);
|
||
|
+
|
||
|
+ BiomeBase prevObj = null;
|
||
|
+ short id = 0;
|
||
|
+
|
||
|
+ for (BiomeBase obj : this.getData()) {
|
||
|
+ if (obj == prevObj) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (map.getShort(obj) < 0) {
|
||
|
+ map.put(obj, id++);
|
||
|
+ }
|
||
|
+
|
||
|
+ prevObj = obj;
|
||
|
+ }
|
||
|
+
|
||
|
+ return map;
|
||
|
+ } // Yatopia end
|
||
|
}
|
||
|
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
||
|
index 8b7fd21e6b366196fbc9cd44a340335c4cf9205f..8b8ecc2d8925b3c209d99e101f6e478b08d86db9 100644
|
||
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
||
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
||
|
@@ -336,6 +336,14 @@ public class Chunk implements IChunkAccess {
|
||
|
|
||
|
// CraftBukkit start
|
||
|
this.bukkitChunk = new org.bukkit.craftbukkit.CraftChunk(this);
|
||
|
+ // Yatopia start - Port hydrogen
|
||
|
+ // Upgrading a ProtoChunk to a Chunk might result in empty sections being copied over
|
||
|
+ // These simply waste memory, and the Chunk will return air blocks for any absent section without issue.
|
||
|
+ for (int i2 = 0; i2 < this.sections.length; i2++) {
|
||
|
+ if (ChunkSection.isEmpty(this.sections[i2])) {
|
||
|
+ this.sections[i2] = null;
|
||
|
+ }
|
||
|
+ } // Yatopia end
|
||
|
}
|
||
|
|
||
|
public org.bukkit.Chunk bukkitChunk;
|
||
|
diff --git a/src/main/java/net/minecraft/server/ChunkRegionLoader.java b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||
|
index 5f04591193d58ba7897194142da5efcbec3763dd..bf4f34b5f4f7473921589b2f001570a38e96c5ce 100644
|
||
|
--- a/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||
|
+++ b/src/main/java/net/minecraft/server/ChunkRegionLoader.java
|
||
|
@@ -70,8 +70,10 @@ public class ChunkRegionLoader {
|
||
|
private static final String UNINITIALISED_SKYLIGHT_TAG = "starlight.skylight_uninit";
|
||
|
private static final String STARLIGHT_VERSION_TAG = "starlight.light_version";
|
||
|
// Tuinity end - rewrite light engine
|
||
|
+ private static final ThreadLocal<NBTTagCompound> CAPTURED_TAGS = new ThreadLocal<>(); // Yatopia - Port Hydrogen
|
||
|
|
||
|
public static InProgressChunkHolder loadChunk(WorldServer worldserver, DefinedStructureManager definedstructuremanager, VillagePlace villageplace, ChunkCoordIntPair chunkcoordintpair, NBTTagCompound nbttagcompound, boolean distinguish) {
|
||
|
+ CAPTURED_TAGS.set(nbttagcompound); // Yatopia
|
||
|
ArrayDeque<Runnable> tasksToExecuteOnMain = new ArrayDeque<>();
|
||
|
// Paper end
|
||
|
ChunkGenerator chunkgenerator = worldserver.getChunkProvider().getChunkGenerator();
|
||
|
@@ -190,10 +192,22 @@ public class ChunkRegionLoader {
|
||
|
} else {
|
||
|
object2 = protochunkticklist1;
|
||
|
}
|
||
|
+ // Yatopia start
|
||
|
+ NBTTagCompound strippedTag = new NBTTagCompound();
|
||
|
+ strippedTag.set("Entities", nbttagcompound1.getList("Entities", 10));
|
||
|
+ strippedTag.set("TileEntities", nbttagcompound1.getList("TileEntities", 10));
|
||
|
+ strippedTag.set("ChunkBukkitValues", nbttagcompound1.get("ChunkBukkitValues"));
|
||
|
+ // Yatopia end
|
||
|
|
||
|
object = new Chunk(worldserver.getMinecraftWorld(), chunkcoordintpair, biomestorage, chunkconverter, (TickList) object1, (TickList) object2, j, achunksection, // Paper start - fix massive nbt memory leak due to lambda. move lambda into a container method to not leak scope. Only clone needed NBT keys.
|
||
|
+ // Yatopia start - Port hydrogen
|
||
|
+ /*
|
||
|
createLoadEntitiesConsumer(new SafeNBTCopy(nbttagcompound1, "TileEntities", "Entities", "ChunkBukkitValues")) // Paper - move CB Chunk PDC into here
|
||
|
+ */
|
||
|
+ createLoadEntitiesConsumer(strippedTag)
|
||
|
+ // Yatopia end
|
||
|
);// Paper end
|
||
|
+ CAPTURED_TAGS.remove(); // Yatopia
|
||
|
((Chunk)object).setBlockNibbles(blockNibbles); // Tuinity - replace light impl
|
||
|
((Chunk)object).setSkyNibbles(skyNibbles); // Tuinity - replace light impl
|
||
|
} else {
|
||
|
diff --git a/src/main/java/net/minecraft/server/DataBits.java b/src/main/java/net/minecraft/server/DataBits.java
|
||
|
index f0c9009fb808ca664a7c3ebaeb8cfa8e2ba7b97e..40e3001bc1742231dcd02cee4423c57d0fd9a991 100644
|
||
|
--- a/src/main/java/net/minecraft/server/DataBits.java
|
||
|
+++ b/src/main/java/net/minecraft/server/DataBits.java
|
||
|
@@ -64,6 +64,7 @@ public class DataBits {
|
||
|
return j1;
|
||
|
}
|
||
|
|
||
|
+ public final void set(int i, int j){ b(i, j); } // Yatopia - OBFHELPER
|
||
|
public final void b(int i, int j) { // Paper - make final for inline
|
||
|
//Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper
|
||
|
//Validate.inclusiveBetween(0L, this.d, (long) j); // Paper
|
||
|
@@ -74,6 +75,7 @@ public class DataBits {
|
||
|
this.b[k] = l & ~(this.d << i1) | ((long) j & this.d) << i1;
|
||
|
}
|
||
|
|
||
|
+ public final int get(int i) { return this.a(i); } // Yatopia - OBFHELPER
|
||
|
public final int a(int i) { // Paper - make final for inline
|
||
|
//Validate.inclusiveBetween(0L, (long) (this.e - 1), (long) i); // Paper
|
||
|
int j = this.b(i);
|
||
|
@@ -88,6 +90,7 @@ public class DataBits {
|
||
|
return this.b;
|
||
|
}
|
||
|
|
||
|
+ public int getSize(){ return b(); } // Yatopia - OBFHELPER
|
||
|
public int b() {
|
||
|
return this.e;
|
||
|
}
|
||
|
diff --git a/src/main/java/net/minecraft/server/IBlockDataHolder.java b/src/main/java/net/minecraft/server/IBlockDataHolder.java
|
||
|
index b19c694cf01bc868dd7c4ec6432b613d19f2ca40..865fd6ef879943634ee2861c6da21ead31306eb2 100644
|
||
|
--- a/src/main/java/net/minecraft/server/IBlockDataHolder.java
|
||
|
+++ b/src/main/java/net/minecraft/server/IBlockDataHolder.java
|
||
|
@@ -8,6 +8,10 @@ import com.google.common.collect.Table;
|
||
|
import com.google.common.collect.UnmodifiableIterator;
|
||
|
import com.mojang.serialization.Codec;
|
||
|
import com.mojang.serialization.MapCodec;
|
||
|
+// Yatopia start
|
||
|
+import me.jellysquid.mods.lithium.common.cache.StatePropertyTableCache;
|
||
|
+import me.jellysquid.mods.lithium.common.collections.FastImmutableTable;
|
||
|
+// Yatopia end
|
||
|
import java.util.Collection;
|
||
|
import java.util.Collections;
|
||
|
import java.util.Iterator;
|
||
|
@@ -143,7 +147,12 @@ public abstract class IBlockDataHolder<O, S> {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+ // Yatopia start - Port hydrogen
|
||
|
+ /*
|
||
|
this.e = (Table) (table.isEmpty() ? table : ArrayTable.create(table));
|
||
|
+ */
|
||
|
+ this.e = new FastImmutableTable<>((table.isEmpty() ? table : ArrayTable.create(table)), StatePropertyTableCache.getTableCache(this.c));
|
||
|
+ // Yatopia end
|
||
|
}
|
||
|
}
|
||
|
|
||
|
diff --git a/src/main/java/net/minecraft/server/NBTTagCompound.java b/src/main/java/net/minecraft/server/NBTTagCompound.java
|
||
|
index 06d5acab794e3ee139a11f9b068e8a359c46db2c..2bc71833fea91f1b7b35a431b1d6905a5738e83c 100644
|
||
|
--- a/src/main/java/net/minecraft/server/NBTTagCompound.java
|
||
|
+++ b/src/main/java/net/minecraft/server/NBTTagCompound.java
|
||
|
@@ -20,6 +20,7 @@ import java.util.Set;
|
||
|
import java.util.UUID;
|
||
|
import java.util.regex.Pattern;
|
||
|
import javax.annotation.Nullable;
|
||
|
+import it.unimi.dsi.fastutil.objects.Object2ObjectMap; // Yatopia
|
||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; // Paper
|
||
|
import org.apache.logging.log4j.LogManager;
|
||
|
import org.apache.logging.log4j.Logger;
|
||
|
@@ -74,7 +75,12 @@ public class NBTTagCompound implements NBTBase {
|
||
|
public final Map<String, NBTBase> map; // Paper
|
||
|
|
||
|
protected NBTTagCompound(Map<String, NBTBase> map) {
|
||
|
+ // Yatopia start - Port hydrogen
|
||
|
+ /*
|
||
|
this.map = map;
|
||
|
+ */
|
||
|
+ this.map = map instanceof Object2ObjectMap ? map : new Object2ObjectOpenHashMap<>(map);
|
||
|
+ // Yatopia end
|
||
|
}
|
||
|
|
||
|
public NBTTagCompound() {
|