Add more patches back
This commit is contained in:
458
patches/server/0071-lithium-chunk.serialization.patch
Normal file
458
patches/server/0071-lithium-chunk.serialization.patch
Normal file
@@ -0,0 +1,458 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: jellysquid3 <jellysquid3@users.noreply.github.com>
|
||||
Date: Mon, 10 Jan 2022 15:27:58 -0500
|
||||
Subject: [PATCH] lithium: chunk.serialization
|
||||
|
||||
Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0
|
||||
You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java b/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..16debe176798f316c122e8e7aef2b50ecb9883a6
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/world/chunk/LithiumHashPalette.java
|
||||
@@ -0,0 +1,189 @@
|
||||
+package me.jellysquid.mods.lithium.common.world.chunk;
|
||||
+
|
||||
+import com.google.common.collect.ImmutableList;
|
||||
+import it.unimi.dsi.fastutil.HashCommon;
|
||||
+import it.unimi.dsi.fastutil.objects.Reference2IntMap;
|
||||
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.List;
|
||||
+import java.util.function.Predicate;
|
||||
+import net.minecraft.core.IdMap;
|
||||
+import net.minecraft.network.FriendlyByteBuf;
|
||||
+import net.minecraft.world.level.chunk.Palette;
|
||||
+import net.minecraft.world.level.chunk.PaletteResize;
|
||||
+
|
||||
+import static it.unimi.dsi.fastutil.Hash.FAST_LOAD_FACTOR;
|
||||
+
|
||||
+/**
|
||||
+ * Generally provides better performance over the vanilla {@link net.minecraft.world.level.chunk.HashMapPalette} when calling
|
||||
+ * {@link LithiumHashPalette#idFor(Object)} through using a faster backing map and reducing pointer chasing.
|
||||
+ */
|
||||
+public class LithiumHashPalette<T> implements Palette<T> {
|
||||
+ private static final int ABSENT_VALUE = -1;
|
||||
+
|
||||
+ private final IdMap<T> idList;
|
||||
+ private final PaletteResize<T> resizeHandler;
|
||||
+ private final int indexBits;
|
||||
+
|
||||
+ private final Reference2IntMap<T> table;
|
||||
+ private T[] entries;
|
||||
+ private int size = 0;
|
||||
+
|
||||
+ public LithiumHashPalette(IdMap<T> idList, PaletteResize<T> resizeHandler, int indexBits, T[] entries, Reference2IntMap<T> table, int size) {
|
||||
+ this.idList = idList;
|
||||
+ this.resizeHandler = resizeHandler;
|
||||
+ this.indexBits = indexBits;
|
||||
+ this.entries = entries;
|
||||
+ this.table = table;
|
||||
+ this.size = size;
|
||||
+ }
|
||||
+
|
||||
+ public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResize<T> resizeHandler, List<T> list) {
|
||||
+ this(idList, bits, resizeHandler);
|
||||
+
|
||||
+ for (T t : list) {
|
||||
+ this.addEntry(t);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("unchecked")
|
||||
+ public LithiumHashPalette(IdMap<T> idList, int bits, PaletteResize<T> resizeHandler) {
|
||||
+ this.idList = idList;
|
||||
+ this.indexBits = bits;
|
||||
+ this.resizeHandler = resizeHandler;
|
||||
+
|
||||
+ int capacity = 1 << bits;
|
||||
+
|
||||
+ this.entries = (T[]) new Object[capacity];
|
||||
+ this.table = new Reference2IntOpenHashMap<>(capacity, FAST_LOAD_FACTOR);
|
||||
+ this.table.defaultReturnValue(ABSENT_VALUE);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int idFor(T obj) {
|
||||
+ int id = this.table.getInt(obj);
|
||||
+
|
||||
+ if (id == ABSENT_VALUE) {
|
||||
+ id = this.computeEntry(obj);
|
||||
+ }
|
||||
+
|
||||
+ return id;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean maybeHas(Predicate<T> predicate) {
|
||||
+ for (int i = 0; i < this.size; ++i) {
|
||||
+ if (predicate.test(this.entries[i])) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ private int computeEntry(T obj) {
|
||||
+ int id = this.addEntry(obj);
|
||||
+
|
||||
+ if (id >= 1 << this.indexBits) {
|
||||
+ if (this.resizeHandler == null) {
|
||||
+ throw new IllegalStateException("Cannot grow");
|
||||
+ } else {
|
||||
+ id = this.resizeHandler.onResize(this.indexBits + 1, obj);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return id;
|
||||
+ }
|
||||
+
|
||||
+ private int addEntry(T obj) {
|
||||
+ int nextId = this.size;
|
||||
+
|
||||
+ if (nextId >= this.entries.length) {
|
||||
+ this.resize(this.size);
|
||||
+ }
|
||||
+
|
||||
+ this.table.put(obj, nextId);
|
||||
+ this.entries[nextId] = obj;
|
||||
+
|
||||
+ this.size++;
|
||||
+
|
||||
+ return nextId;
|
||||
+ }
|
||||
+
|
||||
+ private void resize(int neededCapacity) {
|
||||
+ this.entries = Arrays.copyOf(this.entries, HashCommon.nextPowerOfTwo(neededCapacity + 1));
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public T valueFor(int id) {
|
||||
+ T[] entries = this.entries;
|
||||
+
|
||||
+ if (id >= 0 && id < entries.length) {
|
||||
+ return entries[id];
|
||||
+ }
|
||||
+
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void read(FriendlyByteBuf buf) {
|
||||
+ this.clear();
|
||||
+
|
||||
+ int entryCount = buf.readVarInt();
|
||||
+
|
||||
+ for (int i = 0; i < entryCount; ++i) {
|
||||
+ this.addEntry(this.idList.byId(buf.readVarInt()));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void write(FriendlyByteBuf buf) {
|
||||
+ int size = this.size;
|
||||
+ buf.writeVarInt(size);
|
||||
+
|
||||
+ for (int i = 0; i < size; ++i) {
|
||||
+ buf.writeVarInt(this.idList.getId(this.valueFor(i)));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getSerializedSize() {
|
||||
+ int size = FriendlyByteBuf.getVarIntSize(this.size);
|
||||
+
|
||||
+ for (int i = 0; i < this.size; ++i) {
|
||||
+ size += FriendlyByteBuf.getVarIntSize(this.idList.getId(this.valueFor(i)));
|
||||
+ }
|
||||
+
|
||||
+ return size;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getSize() {
|
||||
+ return this.size;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Palette<T> copy() {
|
||||
+ return new LithiumHashPalette<>(this.idList, this.resizeHandler, this.indexBits, this.entries.clone(), new Reference2IntOpenHashMap<>(this.table), this.size);
|
||||
+ }
|
||||
+
|
||||
+ private void clear() {
|
||||
+ Arrays.fill(this.entries, null);
|
||||
+ this.table.clear();
|
||||
+ this.size = 0;
|
||||
+ }
|
||||
+
|
||||
+ public List<T> getElements() {
|
||||
+ ImmutableList.Builder<T> builder = new ImmutableList.Builder<>();
|
||||
+ for (T entry : this.entries) {
|
||||
+ if (entry != null) {
|
||||
+ builder.add(entry);
|
||||
+ }
|
||||
+ }
|
||||
+ return builder.build();
|
||||
+ }
|
||||
+
|
||||
+ public static <A> Palette<A> create(int bits, IdMap<A> idList, PaletteResize<A> listener, List<A> list) {
|
||||
+ return new LithiumHashPalette<>(idList, bits, listener, list);
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/net/minecraft/util/BitStorage.java b/src/main/java/net/minecraft/util/BitStorage.java
|
||||
index 106610ccc74b70b557b01c61262d56c4f1147acf..fc986f02290fbe20246022072944980f35dd200c 100644
|
||||
--- a/src/main/java/net/minecraft/util/BitStorage.java
|
||||
+++ b/src/main/java/net/minecraft/util/BitStorage.java
|
||||
@@ -1,6 +1,7 @@
|
||||
package net.minecraft.util;
|
||||
|
||||
import java.util.function.IntConsumer;
|
||||
+import net.minecraft.world.level.chunk.Palette; // JettPack
|
||||
|
||||
public interface BitStorage {
|
||||
int getAndSet(int index, int value);
|
||||
@@ -31,4 +32,6 @@ public interface BitStorage {
|
||||
|
||||
}
|
||||
// Paper end
|
||||
+
|
||||
+ <T> void compact(Palette<T> srcPalette, Palette<T> dstPalette, short[] out); // JettPack - lithium: chunk.serialization
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/util/SimpleBitStorage.java b/src/main/java/net/minecraft/util/SimpleBitStorage.java
|
||||
index 36e33923bf48e56c743ed043bcbc66bc32f0422f..0272dee738e86e066108f5cc3729136335d8197e 100644
|
||||
--- a/src/main/java/net/minecraft/util/SimpleBitStorage.java
|
||||
+++ b/src/main/java/net/minecraft/util/SimpleBitStorage.java
|
||||
@@ -2,6 +2,7 @@ package net.minecraft.util;
|
||||
|
||||
import java.util.function.IntConsumer;
|
||||
import javax.annotation.Nullable;
|
||||
+import net.minecraft.world.level.chunk.Palette; // JettPack
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public class SimpleBitStorage implements BitStorage {
|
||||
@@ -201,4 +202,44 @@ public class SimpleBitStorage implements BitStorage {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // JettPack start - lithium: chunk.serialization
|
||||
+ @Override
|
||||
+ public <T> void compact(Palette<T> srcPalette, Palette<T> dstPalette, short[] out) {
|
||||
+ if (this.size >= Short.MAX_VALUE) {
|
||||
+ throw new IllegalStateException("Array too large");
|
||||
+ }
|
||||
+
|
||||
+ if (this.size != out.length) {
|
||||
+ throw new IllegalStateException("Array size mismatch");
|
||||
+ }
|
||||
+
|
||||
+ short[] mappings = new short[(int) (this.mask + 1)];
|
||||
+
|
||||
+ int idx = 0;
|
||||
+
|
||||
+ for (long word : this.data) {
|
||||
+ long bits = word;
|
||||
+
|
||||
+ for (int elementIdx = 0; elementIdx < this.valuesPerLong; ++elementIdx) {
|
||||
+ int value = (int) (bits & this.mask);
|
||||
+ int remappedId = mappings[value];
|
||||
+
|
||||
+ if (remappedId == 0) {
|
||||
+ remappedId = dstPalette.idFor(srcPalette.valueFor(value)) + 1;
|
||||
+ mappings[value] = (short) remappedId;
|
||||
+ }
|
||||
+
|
||||
+ out[idx] = (short) (remappedId - 1);
|
||||
+ bits >>= this.bits;
|
||||
+
|
||||
+ ++idx;
|
||||
+
|
||||
+ if (idx >= this.size) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // JettPack end
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/util/ZeroBitStorage.java b/src/main/java/net/minecraft/util/ZeroBitStorage.java
|
||||
index 97c744508cc535418eba65fa722859c81c22d647..a2ea0a2864b9c4f847f1a14ffc0900e67c18f9ee 100644
|
||||
--- a/src/main/java/net/minecraft/util/ZeroBitStorage.java
|
||||
+++ b/src/main/java/net/minecraft/util/ZeroBitStorage.java
|
||||
@@ -2,6 +2,7 @@ package net.minecraft.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.IntConsumer;
|
||||
+import net.minecraft.world.level.chunk.Palette; // JettPack
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
public class ZeroBitStorage implements BitStorage {
|
||||
@@ -72,4 +73,6 @@ public class ZeroBitStorage implements BitStorage {
|
||||
public BitStorage copy() {
|
||||
return this;
|
||||
}
|
||||
+
|
||||
+ @Override public <T> void compact(Palette<T> srcPalette, Palette<T> dstPalette, short[] out) {} // JettPack
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java b/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java
|
||||
index acae3eb30e0689048937f479dc3070f0688abdad..9c2b79655f2c63a208c7087d5d897db0fb23f697 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/PaletteResize.java
|
||||
@@ -1,5 +1,5 @@
|
||||
package net.minecraft.world.level.chunk;
|
||||
|
||||
-interface PaletteResize<T> {
|
||||
+public interface PaletteResize<T> { // JettPack - make public
|
||||
int onResize(int newBits, T object);
|
||||
}
|
||||
diff --git a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
index 08e1309e618377d170c446a1568c21b7bf4e5683..0b4f66d0ef963d6f47b20469b7a1e3f6c3da7c83 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/chunk/PalettedContainer.java
|
||||
@@ -22,8 +22,23 @@ import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.SimpleBitStorage;
|
||||
import net.minecraft.util.ThreadingDetector;
|
||||
import net.minecraft.util.ZeroBitStorage;
|
||||
+import me.jellysquid.mods.lithium.common.world.chunk.LithiumHashPalette; // JettPack
|
||||
|
||||
public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainerRO<T> {
|
||||
+ // JettPack start - lithium: chunk.serialization
|
||||
+ private static final ThreadLocal<short[]> CACHED_ARRAY_4096 = ThreadLocal.withInitial(() -> new short[4096]);
|
||||
+ private static final ThreadLocal<short[]> CACHED_ARRAY_64 = ThreadLocal.withInitial(() -> new short[64]);
|
||||
+ private Optional<LongStream> asOptional(long[] data) {
|
||||
+ return Optional.of(Arrays.stream(data));
|
||||
+ }
|
||||
+ private short[] getOrCreate(int size) {
|
||||
+ return switch (size) {
|
||||
+ case 64 -> CACHED_ARRAY_64.get();
|
||||
+ case 4096 -> CACHED_ARRAY_4096.get();
|
||||
+ default -> new short[size];
|
||||
+ };
|
||||
+ }
|
||||
+ // JettPack end
|
||||
private static final int MIN_PALETTE_BITS = 0;
|
||||
private final PaletteResize<T> dummyPaletteResize = (newSize, added) -> {
|
||||
return 0;
|
||||
@@ -298,30 +313,54 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
public synchronized PalettedContainerRO.PackedData<T> pack(IdMap<T> idMap, PalettedContainer.Strategy strategy) { // Paper - synchronize
|
||||
this.acquire();
|
||||
|
||||
- PalettedContainerRO.PackedData var12;
|
||||
+ // JettPack start - lithium: chunk.serialization
|
||||
+ Optional<LongStream> data = Optional.empty();
|
||||
+ List<T> elements = null;
|
||||
try {
|
||||
- HashMapPalette<T> hashMapPalette = new HashMapPalette<>(idMap, this.data.storage.getBits(), this.dummyPaletteResize);
|
||||
- int i = strategy.size();
|
||||
- int[] is = new int[i];
|
||||
- this.data.storage.unpack(is);
|
||||
- swapPalette(is, (ix) -> {
|
||||
- return hashMapPalette.idFor(this.data.palette.valueFor(ix));
|
||||
- });
|
||||
- int j = strategy.calculateBitsForSerialization(idMap, hashMapPalette.getSize());
|
||||
- Optional<LongStream> optional;
|
||||
- if (j != 0) {
|
||||
- SimpleBitStorage simpleBitStorage = new SimpleBitStorage(j, i, is);
|
||||
- optional = Optional.of(Arrays.stream(simpleBitStorage.getRaw()));
|
||||
- } else {
|
||||
- optional = Optional.empty();
|
||||
+ // The palette that will be serialized
|
||||
+ LithiumHashPalette<T> hashPalette = null;
|
||||
+
|
||||
+ final Palette<T> palette = this.data.palette();
|
||||
+ final BitStorage storage = this.data.storage();
|
||||
+ if (storage instanceof ZeroBitStorage || palette.getSize() == 1) {
|
||||
+ // If the palette only contains one entry, don't attempt to repack it.
|
||||
+ elements = List.of(palette.valueFor(0));
|
||||
+ } else if (palette instanceof LithiumHashPalette<T> lithiumHashPalette) {
|
||||
+ hashPalette = lithiumHashPalette;
|
||||
}
|
||||
|
||||
- var12 = new PalettedContainerRO.PackedData<>(hashMapPalette.getEntries(), optional);
|
||||
+ if (elements == null) {
|
||||
+ LithiumHashPalette<T> compactedPalette = new LithiumHashPalette<>(idMap, storage.getBits(), this.dummyPaletteResize);
|
||||
+ short[] array = this.getOrCreate(strategy.size());
|
||||
+
|
||||
+ storage.compact(this.data.palette(), compactedPalette, array);
|
||||
+
|
||||
+ // If the palette didn't change during compaction, do a simple copy of the data array
|
||||
+ if (hashPalette != null && hashPalette.getSize() == compactedPalette.getSize() && storage.getBits() == strategy.calculateBitsForSerialization(idMap, hashPalette.getSize())) { // paletteSize can de-sync from palette - see https://github.com/CaffeineMC/lithium-fabric/issues/279
|
||||
+ data = this.asOptional(storage.getRaw().clone());
|
||||
+ elements = hashPalette.getElements();
|
||||
+ } else {
|
||||
+ int bits = strategy.calculateBitsForSerialization(idMap, compactedPalette.getSize());
|
||||
+ if (bits != 0) {
|
||||
+ // Re-pack the integer array as the palette has changed size
|
||||
+ SimpleBitStorage copy = new SimpleBitStorage(bits, array.length);
|
||||
+ for (int i = 0; i < array.length; ++i) {
|
||||
+ copy.set(i, array[i]);
|
||||
+ }
|
||||
+
|
||||
+ // We don't need to clone the data array as we are the sole owner of it
|
||||
+ data = this.asOptional(copy.getRaw());
|
||||
+ }
|
||||
+
|
||||
+ elements = compactedPalette.getElements();
|
||||
+ }
|
||||
+ }
|
||||
} finally {
|
||||
this.release();
|
||||
}
|
||||
|
||||
- return var12;
|
||||
+ return new PalettedContainerRO.PackedData<>(elements, data);
|
||||
+ // JettPack end
|
||||
}
|
||||
|
||||
private static <T> void swapPalette(int[] is, IntUnaryOperator intUnaryOperator) {
|
||||
@@ -361,17 +400,37 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
||||
|
||||
@Override
|
||||
public void count(PalettedContainer.CountConsumer<T> counter) {
|
||||
- if (this.data.palette.getSize() == 1) {
|
||||
- counter.accept(this.data.palette.valueFor(0), this.data.storage.getSize());
|
||||
- } else {
|
||||
- Int2IntOpenHashMap int2IntOpenHashMap = new Int2IntOpenHashMap();
|
||||
- this.data.storage.getAll((key) -> {
|
||||
- int2IntOpenHashMap.addTo(key, 1);
|
||||
- });
|
||||
- int2IntOpenHashMap.int2IntEntrySet().forEach((entry) -> {
|
||||
- counter.accept(this.data.palette.valueFor(entry.getIntKey()), entry.getIntValue());
|
||||
- });
|
||||
+ // JettPack start - lithium: chunk.serialization
|
||||
+ int len = this.data.palette().getSize();
|
||||
+
|
||||
+ // Do not allocate huge arrays if we're using a large palette
|
||||
+ if (len > 4096) {
|
||||
+ // VanillaCopy
|
||||
+ if (this.data.palette.getSize() == 1) {
|
||||
+ counter.accept(this.data.palette.valueFor(0), this.data.storage.getSize());
|
||||
+ } else {
|
||||
+ Int2IntOpenHashMap int2IntOpenHashMap = new Int2IntOpenHashMap();
|
||||
+ this.data.storage.getAll((key) -> {
|
||||
+ int2IntOpenHashMap.addTo(key, 1);
|
||||
+ });
|
||||
+ int2IntOpenHashMap.int2IntEntrySet().forEach((entry) -> {
|
||||
+ counter.accept(this.data.palette.valueFor(entry.getIntKey()), entry.getIntValue());
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ short[] counts = new short[len];
|
||||
+
|
||||
+ this.data.storage().getAll(i -> counts[i]++);
|
||||
+
|
||||
+ for (int i = 0; i < counts.length; i++) {
|
||||
+ T obj = this.data.palette().valueFor(i);
|
||||
+
|
||||
+ if (obj != null) {
|
||||
+ counter.accept(obj, counts[i]);
|
||||
+ }
|
||||
}
|
||||
+ // JettPack end
|
||||
}
|
||||
|
||||
static record Configuration<T>(Palette.Factory factory, int bits) {
|
||||
175
patches/server/0079-lithium-cache-iterate-outwards.patch
Normal file
175
patches/server/0079-lithium-cache-iterate-outwards.patch
Normal file
@@ -0,0 +1,175 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: 2No2Name <2No2Name@web.de>
|
||||
Date: Thu, 13 Jan 2022 15:38:29 -0500
|
||||
Subject: [PATCH] lithium: cache iterate outwards
|
||||
|
||||
Original code by the PR below, licensed under GNU Lesser General Public License v3.0
|
||||
You can find the original code on https://github.com/CaffeineMC/lithium-fabric/pull/123 (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a5d3aa309d3fdaab9e0fea2dfb91a080a3ac1193
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/IterateOutwardsCache.java
|
||||
@@ -0,0 +1,71 @@
|
||||
+package me.jellysquid.mods.lithium.common.cached_blockpos_iteration;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
+import it.unimi.dsi.fastutil.longs.LongList;
|
||||
+import java.util.Iterator;
|
||||
+import java.util.Random;
|
||||
+import java.util.concurrent.ConcurrentHashMap;
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+
|
||||
+/**
|
||||
+ * @author 2No2Name, original implemenation by SuperCoder7979 and Gegy1000
|
||||
+ */
|
||||
+public class IterateOutwardsCache {
|
||||
+ //POS_ZERO must not be replaced with BlockPos.ORIGIN, otherwise iterateOutwards at BlockPos.ORIGIN will not use the cache
|
||||
+ public static final BlockPos POS_ZERO = new BlockPos(0,0,0);
|
||||
+
|
||||
+
|
||||
+ private final ConcurrentHashMap<Long, LongArrayList> table;
|
||||
+ private final int capacity;
|
||||
+ private final Random random;
|
||||
+
|
||||
+ public IterateOutwardsCache(int capacity) {
|
||||
+ this.capacity = capacity;
|
||||
+ this.table = new ConcurrentHashMap<>(31);
|
||||
+ this.random = new Random();
|
||||
+ }
|
||||
+
|
||||
+ private void fillPositionsWithIterateOutwards(LongList entry, int xRange, int yRange, int zRange) {
|
||||
+ // Add all positions to the cached list
|
||||
+ for (BlockPos pos : BlockPos.withinManhattan(POS_ZERO, xRange, yRange, zRange)) {
|
||||
+ entry.add(pos.asLong());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public LongList getOrCompute(int xRange, int yRange, int zRange) {
|
||||
+ long key = BlockPos.asLong(xRange, yRange, zRange);
|
||||
+
|
||||
+ LongArrayList entry = this.table.get(key);
|
||||
+ if (entry != null) {
|
||||
+ return entry;
|
||||
+ }
|
||||
+
|
||||
+ // Cache miss: compute and store
|
||||
+ entry = new LongArrayList(128);
|
||||
+
|
||||
+ this.fillPositionsWithIterateOutwards(entry, xRange, yRange, zRange);
|
||||
+
|
||||
+ //decrease the array size, as of now it won't be modified anymore anyways
|
||||
+ entry.trim();
|
||||
+
|
||||
+ //this might overwrite an entry as the same entry could have been computed and added during this thread's computation
|
||||
+ //we do not use computeIfAbsent, as it can delay other threads for too long
|
||||
+ Object previousEntry = this.table.put(key, entry);
|
||||
+
|
||||
+
|
||||
+ if (previousEntry == null && this.table.size() > this.capacity) {
|
||||
+ //prevent a memory leak by randomly removing about 1/8th of the elements when the exceed the desired capacity is exceeded
|
||||
+ final Iterator<Long> iterator = this.table.keySet().iterator();
|
||||
+ //prevent an unlikely infinite loop caused by another thread filling the table concurrently using counting
|
||||
+ for (int i = -this.capacity; iterator.hasNext() && i < 5; i++) {
|
||||
+ Long key2 = iterator.next();
|
||||
+ //random is not threadsafe, but it doesn't matter here, because we don't need quality random numbers
|
||||
+ if (this.random.nextInt(8) == 0 && key2 != key) {
|
||||
+ iterator.remove();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return entry;
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..493661ff3ac7247b68b7b02784b09b0eaf88fc52
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/cached_blockpos_iteration/LongList2BlockPosMutableIterable.java
|
||||
@@ -0,0 +1,46 @@
|
||||
+package me.jellysquid.mods.lithium.common.cached_blockpos_iteration;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
+import it.unimi.dsi.fastutil.longs.LongList;
|
||||
+import java.util.Iterator;
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+
|
||||
+/**
|
||||
+ * @author 2No2Name
|
||||
+ */
|
||||
+public class LongList2BlockPosMutableIterable implements Iterable<BlockPos> {
|
||||
+
|
||||
+ private final LongList positions;
|
||||
+ private final int xOffset, yOffset, zOffset;
|
||||
+
|
||||
+ public LongList2BlockPosMutableIterable(BlockPos offset, LongList posList) {
|
||||
+ this.xOffset = offset.getX();
|
||||
+ this.yOffset = offset.getY();
|
||||
+ this.zOffset = offset.getZ();
|
||||
+ this.positions = posList;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public Iterator<BlockPos> iterator() {
|
||||
+ return new Iterator<BlockPos>() {
|
||||
+
|
||||
+ private final LongIterator it = LongList2BlockPosMutableIterable.this.positions.iterator();
|
||||
+ private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean hasNext() {
|
||||
+ return it.hasNext();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public net.minecraft.core.BlockPos next() {
|
||||
+ long nextPos = this.it.nextLong();
|
||||
+ return this.pos.set(
|
||||
+ LongList2BlockPosMutableIterable.this.xOffset + BlockPos.getX(nextPos),
|
||||
+ LongList2BlockPosMutableIterable.this.yOffset + BlockPos.getY(nextPos),
|
||||
+ LongList2BlockPosMutableIterable.this.zOffset + BlockPos.getZ(nextPos));
|
||||
+ }
|
||||
+ };
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/net/minecraft/core/BlockPos.java b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
index 153451ecd5b3c8e8ecb2d5ec91ccd582d4300899..4487752469f9ab95e9d2aeb76a9627dc02095d76 100644
|
||||
--- a/src/main/java/net/minecraft/core/BlockPos.java
|
||||
+++ b/src/main/java/net/minecraft/core/BlockPos.java
|
||||
@@ -18,6 +18,12 @@ import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.slf4j.Logger;
|
||||
+// JettPack start
|
||||
+import it.unimi.dsi.fastutil.longs.LongList;
|
||||
+import me.jellysquid.mods.lithium.common.cached_blockpos_iteration.IterateOutwardsCache;
|
||||
+import me.jellysquid.mods.lithium.common.cached_blockpos_iteration.LongList2BlockPosMutableIterable;
|
||||
+import static me.jellysquid.mods.lithium.common.cached_blockpos_iteration.IterateOutwardsCache.POS_ZERO;
|
||||
+// JettPack end
|
||||
|
||||
@Immutable
|
||||
public class BlockPos extends Vec3i {
|
||||
@@ -284,7 +290,18 @@ public class BlockPos extends Vec3i {
|
||||
};
|
||||
}
|
||||
|
||||
+ // JettPack start - lithium: cached iterate outwards
|
||||
+ private static final IterateOutwardsCache ITERATE_OUTWARDS_CACHE = new IterateOutwardsCache(50);
|
||||
+ private static final LongList HOGLIN_PIGLIN_CACHE = ITERATE_OUTWARDS_CACHE.getOrCompute(8, 4, 8);
|
||||
+ // JettPack end
|
||||
+
|
||||
public static Iterable<BlockPos> withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ) {
|
||||
+ // JettPack start - lithium: cached iterate outwards
|
||||
+ if (center != POS_ZERO) {
|
||||
+ final LongList positions = rangeX == 8 && rangeY == 4 && rangeZ == 8 ? HOGLIN_PIGLIN_CACHE : ITERATE_OUTWARDS_CACHE.getOrCompute(rangeX, rangeY, rangeZ);
|
||||
+ return new LongList2BlockPosMutableIterable(center, positions);
|
||||
+ }
|
||||
+ // JettPack end
|
||||
int i = rangeX + rangeY + rangeZ;
|
||||
// Paper start - rename variables to fix conflict with anonymous class (remap fix)
|
||||
int centerX = center.getX();
|
||||
79
patches/server/0080-lithium-ai.raid.patch
Normal file
79
patches/server/0080-lithium-ai.raid.patch
Normal file
@@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: jellysquid3 <jellysquid3@users.noreply.github.com>
|
||||
Date: Tue, 18 Jan 2022 10:37:18 -0500
|
||||
Subject: [PATCH] lithium: ai.raid
|
||||
|
||||
Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0
|
||||
You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/raid/Raid.java b/src/main/java/net/minecraft/world/entity/raid/Raid.java
|
||||
index 6a0a1731fd6804eb69d3641213712d31bce085b2..5f4bb589474ce7d4f214e32ab0bc4b9cb71638d0 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/raid/Raid.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/raid/Raid.java
|
||||
@@ -269,7 +269,16 @@ public class Raid {
|
||||
this.status = Raid.RaidStatus.STOPPED;
|
||||
}
|
||||
|
||||
+ private boolean isBarDirty; // JettPack
|
||||
public void tick() {
|
||||
+ // JettPack start - lithium: ai.raid
|
||||
+ if (this.isBarDirty) {
|
||||
+ this.raidEvent.setProgress(Mth.clamp(this.getHealthOfLivingRaiders() / this.totalHealth, 0.0F, 1.0F));
|
||||
+
|
||||
+ this.isBarDirty = false;
|
||||
+ }
|
||||
+ // JettPack end
|
||||
+
|
||||
if (!this.isStopped()) {
|
||||
if (this.status == Raid.RaidStatus.ONGOING) {
|
||||
boolean flag = this.active;
|
||||
@@ -626,7 +635,7 @@ public class Raid {
|
||||
}
|
||||
|
||||
public void updateBossbar() {
|
||||
- this.raidEvent.setProgress(Mth.clamp(this.getHealthOfLivingRaiders() / this.totalHealth, 0.0F, 1.0F));
|
||||
+ this.isBarDirty = true; // JettPack - lithium: ai.raid
|
||||
}
|
||||
|
||||
public float getHealthOfLivingRaiders() {
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/raid/Raider.java b/src/main/java/net/minecraft/world/entity/raid/Raider.java
|
||||
index 4bb9730b6a42702e91467f980b9f045585039db3..7ba9c7f995c2bacc8f9a86a78747ea30f45eb59a 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/raid/Raider.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/raid/Raider.java
|
||||
@@ -46,8 +46,9 @@ import net.minecraft.world.phys.Vec3;
|
||||
public abstract class Raider extends PatrollingMonster {
|
||||
|
||||
protected static final EntityDataAccessor<Boolean> IS_CELEBRATING = SynchedEntityData.defineId(Raider.class, EntityDataSerializers.BOOLEAN);
|
||||
+ public static final ItemStack CACHED_OMINOUS_BANNER = Raid.getLeaderBannerInstance(); // JettPack - lithium: ai.raid
|
||||
static final Predicate<ItemEntity> ALLOWED_ITEMS = (entityitem) -> {
|
||||
- return !entityitem.hasPickUpDelay() && entityitem.isAlive() && ItemStack.matches(entityitem.getItem(), Raid.getLeaderBannerInstance());
|
||||
+ return !entityitem.hasPickUpDelay() && entityitem.isAlive() && ItemStack.matches(entityitem.getItem(), CACHED_OMINOUS_BANNER); // JettPack - lithium: ai.raid
|
||||
};
|
||||
@Nullable
|
||||
protected Raid raid;
|
||||
@@ -149,7 +150,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
}
|
||||
}
|
||||
|
||||
- if (!itemstack.isEmpty() && ItemStack.matches(itemstack, Raid.getLeaderBannerInstance()) && entityhuman != null) {
|
||||
+ if (!itemstack.isEmpty() && ItemStack.matches(itemstack, CACHED_OMINOUS_BANNER) && entityhuman != null) { // JettPack - lithium: ai.raid
|
||||
MobEffectInstance mobeffect = entityhuman.getEffect(MobEffects.BAD_OMEN);
|
||||
byte b0 = 1;
|
||||
int i;
|
||||
@@ -304,6 +305,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
public class ObtainRaidLeaderBannerGoal<T extends Raider> extends Goal {
|
||||
|
||||
private final T mob;
|
||||
+ private static final ItemStack CACHED_OMINOUS_BANNER = Raid.getLeaderBannerInstance(); // JettPack
|
||||
|
||||
public ObtainRaidLeaderBannerGoal(T entityraider) { // CraftBukkit - decompile error
|
||||
this.mob = entityraider;
|
||||
@@ -315,7 +317,7 @@ public abstract class Raider extends PatrollingMonster {
|
||||
if (!this.mob.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) || !this.mob.canPickUpLoot()) return false; // Paper - respect game and entity rules for picking up items
|
||||
Raid raid = this.mob.getCurrentRaid();
|
||||
|
||||
- if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), Raid.getLeaderBannerInstance())) {
|
||||
+ if (this.mob.hasActiveRaid() && !this.mob.getCurrentRaid().isOver() && this.mob.canBeLeader() && !ItemStack.matches(this.mob.getItemBySlot(EquipmentSlot.HEAD), CACHED_OMINOUS_BANNER)) { // JettPack - lithium: ai.raid
|
||||
Raider entityraider = raid.getLeader(this.mob.getWave());
|
||||
|
||||
if (entityraider == null || !entityraider.isAlive()) {
|
||||
@@ -1,38 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com>
|
||||
Date: Fri, 22 Jan 2021 16:38:19 -0500
|
||||
Subject: [PATCH] lithium: gen.cached_generator_settings
|
||||
|
||||
Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0
|
||||
You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
index df1db87d2dd5076fccea6a1ac9271a9d786729bb..47e611d674865f4c6e36032df61bb9bf284f5286 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
@@ -67,6 +67,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
|
||||
public final Registry<NormalNoise.NoiseParameters> noises;
|
||||
public final Holder<NoiseGeneratorSettings> settings;
|
||||
private final Aquifer.FluidPicker globalFluidPicker;
|
||||
+ private final int cachedSeaLevel; // Mirai - lithium: gen.cached_generator_settings
|
||||
|
||||
public NoiseBasedChunkGenerator(Registry<StructureSet> structureSetRegistry, Registry<NormalNoise.NoiseParameters> noiseRegistry, BiomeSource populationSource, Holder<NoiseGeneratorSettings> holder) {
|
||||
super(structureSetRegistry, Optional.empty(), populationSource);
|
||||
@@ -83,6 +84,8 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
|
||||
this.globalFluidPicker = (j, k, l) -> {
|
||||
return k < Math.min(-54, i) ? aquifer_b : aquifer_b1;
|
||||
};
|
||||
+
|
||||
+ this.cachedSeaLevel = ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); // Mirai - lithium: gen.cached_generator_settings
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -400,7 +403,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
|
||||
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
- return ((NoiseGeneratorSettings) this.settings.value()).seaLevel();
|
||||
+ return this.cachedSeaLevel; // Mirai - lithium: gen.cached_generator_settings
|
||||
}
|
||||
|
||||
@Override
|
||||
243
patches/server/0083-lithium-gen.patch
Normal file
243
patches/server/0083-lithium-gen.patch
Normal file
@@ -0,0 +1,243 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SuperCoder7979 <25208576+SuperCoder7979@users.noreply.github.com>
|
||||
Date: Fri, 22 Jan 2021 16:38:19 -0500
|
||||
Subject: [PATCH] lithium: gen
|
||||
|
||||
Original code by CaffeineMC, licensed under GNU Lesser General Public License v3.0
|
||||
You can find the original code on https://github.com/CaffeineMC/lithium-fabric (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/Pos.java b/src/main/java/me/jellysquid/mods/lithium/common/util/Pos.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c99eff34c1be07508c88fe9525c3ae1a087fdef7
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/util/Pos.java
|
||||
@@ -0,0 +1,92 @@
|
||||
+package me.jellysquid.mods.lithium.common.util;
|
||||
+
|
||||
+import net.minecraft.core.SectionPos;
|
||||
+import net.minecraft.world.level.LevelHeightAccessor;
|
||||
+
|
||||
+public class Pos {
|
||||
+
|
||||
+ public static class BlockCoord {
|
||||
+ public static int getYSize(LevelHeightAccessor view) {
|
||||
+ return view.getHeight();
|
||||
+ }
|
||||
+ public static int getMinY(LevelHeightAccessor view) {
|
||||
+ return view.getMinBuildHeight();
|
||||
+ }
|
||||
+ public static int getMaxYInclusive(LevelHeightAccessor view) {
|
||||
+ return view.getMaxBuildHeight() - 1;
|
||||
+ }
|
||||
+ public static int getMaxYExclusive(LevelHeightAccessor view) {
|
||||
+ return view.getMaxBuildHeight();
|
||||
+ }
|
||||
+
|
||||
+ public static int getMaxInSectionCoord(int sectionCoord) {
|
||||
+ return 15 + getMinInSectionCoord(sectionCoord);
|
||||
+ }
|
||||
+
|
||||
+ public static int getMaxYInSectionIndex(LevelHeightAccessor view, int sectionIndex){
|
||||
+ return getMaxInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex));
|
||||
+ }
|
||||
+
|
||||
+ public static int getMinInSectionCoord(int sectionCoord) {
|
||||
+ return SectionPos.sectionToBlockCoord(sectionCoord);
|
||||
+ }
|
||||
+
|
||||
+ public static int getMinYInSectionIndex(LevelHeightAccessor view, int sectionIndex) {
|
||||
+ return getMinInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static class ChunkCoord {
|
||||
+ public static int fromBlockCoord(int blockCoord) {
|
||||
+ return SectionPos.blockToSectionCoord(blockCoord);
|
||||
+ }
|
||||
+
|
||||
+ public static int fromBlockSize(int i) {
|
||||
+ return i >> 4; //same method as fromBlockCoord, just be clear about coord/size semantic difference
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static class SectionYCoord {
|
||||
+ public static int getNumYSections(LevelHeightAccessor view) {
|
||||
+ return view.getSectionsCount();
|
||||
+ }
|
||||
+ public static int getMinYSection(LevelHeightAccessor view) {
|
||||
+ return view.getMinSection();
|
||||
+ }
|
||||
+ public static int getMaxYSectionInclusive(LevelHeightAccessor view) {
|
||||
+ return view.getMaxSection() - 1;
|
||||
+ }
|
||||
+ public static int getMaxYSectionExclusive(LevelHeightAccessor view) {
|
||||
+ return view.getMaxSection();
|
||||
+ }
|
||||
+
|
||||
+ public static int fromSectionIndex(LevelHeightAccessor view, int sectionCoord) {
|
||||
+ return sectionCoord + SectionYCoord.getMinYSection(view);
|
||||
+ }
|
||||
+ public static int fromBlockCoord(int blockCoord) {
|
||||
+ return SectionPos.blockToSectionCoord(blockCoord);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static class SectionYIndex {
|
||||
+ public static int getNumYSections(LevelHeightAccessor view) {
|
||||
+ return view.getSectionsCount();
|
||||
+ }
|
||||
+ public static int getMinYSectionIndex(LevelHeightAccessor view) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ public static int getMaxYSectionIndexInclusive(LevelHeightAccessor view) {
|
||||
+ return view.getSectionsCount() - 1;
|
||||
+ }
|
||||
+ public static int getMaxYSectionIndexExclusive(LevelHeightAccessor view) {
|
||||
+ return view.getSectionsCount();
|
||||
+ }
|
||||
+
|
||||
+ public static int fromSectionCoord(LevelHeightAccessor view, int sectionCoord) {
|
||||
+ return sectionCoord - SectionYCoord.getMinYSection(view);
|
||||
+ }
|
||||
+ public static int fromBlockCoord(LevelHeightAccessor view, int blockCoord) {
|
||||
+ return fromSectionCoord(view, SectionPos.blockToSectionCoord(blockCoord));
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/net/minecraft/server/level/WorldGenRegion.java b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
index d37ba3fec0e4011629a5fbc88d377d52267ad395..4967605f46a58ad9888c6a997f950f50d1bd5d1e 100644
|
||||
--- a/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
+++ b/src/main/java/net/minecraft/server/level/WorldGenRegion.java
|
||||
@@ -53,6 +53,7 @@ import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.ticks.LevelTickAccess;
|
||||
import net.minecraft.world.ticks.WorldGenTickAccess;
|
||||
import org.slf4j.Logger;
|
||||
+import me.jellysquid.mods.lithium.common.util.Pos; // Mirai - lithium: gen
|
||||
|
||||
public class WorldGenRegion implements WorldGenLevel {
|
||||
|
||||
@@ -81,6 +82,8 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
private Supplier<String> currentlyGenerating;
|
||||
private final AtomicLong subTickCount = new AtomicLong();
|
||||
private static final ResourceLocation WORLDGEN_REGION_RANDOM = new ResourceLocation("worldgen_region_random");
|
||||
+ private ChunkAccess[] chunksArr; // Mirai - lithium: gen
|
||||
+ private int minChunkX, minChunkZ; // Mirai - lithium: gen
|
||||
|
||||
public WorldGenRegion(ServerLevel world, List<ChunkAccess> chunks, ChunkStatus status, int placementRadius) {
|
||||
this.generatingStatus = status;
|
||||
@@ -103,6 +106,12 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
this.lastPos = ((ChunkAccess) chunks.get(chunks.size() - 1)).getPos();
|
||||
this.structureManager = world.structureManager().forWorldGenRegion(this);
|
||||
}
|
||||
+ // Mirai start - lithium: gen
|
||||
+ this.minChunkX = this.firstPos.x;
|
||||
+ this.minChunkZ = this.firstPos.z;
|
||||
+
|
||||
+ this.chunksArr = chunks.toArray(new ChunkAccess[0]);
|
||||
+ // Mirai end
|
||||
}
|
||||
|
||||
public boolean isOldChunkAround(ChunkPos chunkPos, int checkRadius) {
|
||||
@@ -118,11 +127,33 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
this.currentlyGenerating = structureName;
|
||||
}
|
||||
|
||||
+ // Mirai start - lithium: gen
|
||||
+ /**
|
||||
+ * @reason Use the chunk array for faster access
|
||||
+ * @author SuperCoder7979, 2No2Name
|
||||
+ */
|
||||
@Override
|
||||
public ChunkAccess getChunk(int chunkX, int chunkZ) {
|
||||
- return this.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY);
|
||||
+ int x = chunkX - this.minChunkX;
|
||||
+ int z = chunkZ - this.minChunkZ;
|
||||
+ int w = this.size;
|
||||
+
|
||||
+ if (x >= 0 && z >= 0 && x < w && z < w) {
|
||||
+ return this.chunksArr[x + z * w];
|
||||
+ } else {
|
||||
+ throw new NullPointerException("No chunk exists at " + new ChunkPos(chunkX, chunkZ));
|
||||
+ }
|
||||
}
|
||||
|
||||
+ /**
|
||||
+ * Use our chunk fetch function
|
||||
+ */
|
||||
+ public ChunkAccess getChunk(BlockPos pos) {
|
||||
+ // Skip checking chunk.getStatus().isAtLeast(ChunkStatus.EMPTY) here, because it is always true
|
||||
+ return this.getChunk(Pos.ChunkCoord.fromBlockCoord(pos.getX()), Pos.ChunkCoord.fromBlockCoord(pos.getZ()));
|
||||
+ }
|
||||
+ // Mirai end
|
||||
+
|
||||
@Nullable
|
||||
@Override
|
||||
public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) {
|
||||
@@ -178,10 +209,24 @@ public class WorldGenRegion implements WorldGenLevel {
|
||||
}
|
||||
// Paper end
|
||||
|
||||
+ // Mirai start - lithium: gen
|
||||
+ /**
|
||||
+ * @reason Avoid pointer de-referencing, make method easier to inline
|
||||
+ * @author JellySquid
|
||||
+ */
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos) {
|
||||
- return this.getChunk(SectionPos.blockToSectionCoord(pos.getX()), SectionPos.blockToSectionCoord(pos.getZ())).getBlockState(pos);
|
||||
+ int x = (Pos.ChunkCoord.fromBlockCoord(pos.getX())) - this.minChunkX;
|
||||
+ int z = (Pos.ChunkCoord.fromBlockCoord(pos.getZ())) - this.minChunkZ;
|
||||
+ int w = this.size;
|
||||
+
|
||||
+ if (x >= 0 && z >= 0 && x < w && z < w) {
|
||||
+ return this.chunksArr[x + z * w].getBlockState(pos);
|
||||
+ } else {
|
||||
+ throw new NullPointerException("No chunk exists at " + new ChunkPos(pos));
|
||||
+ }
|
||||
}
|
||||
+ // Mirai end
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
index df1db87d2dd5076fccea6a1ac9271a9d786729bb..a9be97c61714597dd68fbe196c90b214a4cd9647 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator.java
|
||||
@@ -67,6 +67,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
|
||||
public final Registry<NormalNoise.NoiseParameters> noises;
|
||||
public final Holder<NoiseGeneratorSettings> settings;
|
||||
private final Aquifer.FluidPicker globalFluidPicker;
|
||||
+ private int cachedSeaLevel; // Mirai - lithium: gen
|
||||
|
||||
public NoiseBasedChunkGenerator(Registry<StructureSet> structureSetRegistry, Registry<NormalNoise.NoiseParameters> noiseRegistry, BiomeSource populationSource, Holder<NoiseGeneratorSettings> holder) {
|
||||
super(structureSetRegistry, Optional.empty(), populationSource);
|
||||
@@ -83,6 +84,7 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
|
||||
this.globalFluidPicker = (j, k, l) -> {
|
||||
return k < Math.min(-54, i) ? aquifer_b : aquifer_b1;
|
||||
};
|
||||
+ this.cachedSeaLevel = ((NoiseGeneratorSettings) this.settings.value()).seaLevel(); // Mirai - lithium: gen
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -398,10 +400,19 @@ public final class NoiseBasedChunkGenerator extends ChunkGenerator {
|
||||
return ((NoiseGeneratorSettings) this.settings.value()).noiseSettings().height();
|
||||
}
|
||||
|
||||
+ // Mirai start - lithium: gen
|
||||
+ /**
|
||||
+ * Use cached sea level instead of retrieving from the registry every time.
|
||||
+ * This method is called for every block in the chunk so this will save a lot of registry lookups.
|
||||
+ *
|
||||
+ * @author SuperCoder79
|
||||
+ * @reason avoid registry lookup
|
||||
+ */
|
||||
@Override
|
||||
public int getSeaLevel() {
|
||||
- return ((NoiseGeneratorSettings) this.settings.value()).seaLevel();
|
||||
+ return this.cachedSeaLevel;
|
||||
}
|
||||
+ // Mirai end
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
258
patches/server/0087-c2me-reduce_allocs.patch
Normal file
258
patches/server/0087-c2me-reduce_allocs.patch
Normal file
@@ -0,0 +1,258 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: ishland <ishlandmc@yeah.net>
|
||||
Date: Mon, 24 Jan 2022 10:56:10 -0500
|
||||
Subject: [PATCH] c2me: reduce_allocs
|
||||
|
||||
Copyright (c) 2021-2022 ishland
|
||||
|
||||
Original code by RelativityMC, licensed under MIT
|
||||
You can find the original code on https://github.com/RelativityMC/C2ME-fabric (Yarn mappings)
|
||||
|
||||
diff --git a/src/main/java/com/ishland/c2me/opts/allocs/common/ObjectCachingUtils.java b/src/main/java/com/ishland/c2me/opts/allocs/common/ObjectCachingUtils.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b1229bae2e74d22065c723c6d3eaf9a97d572b04
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/ishland/c2me/opts/allocs/common/ObjectCachingUtils.java
|
||||
@@ -0,0 +1,23 @@
|
||||
+package com.ishland.c2me.opts.allocs.common;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
+
|
||||
+import java.util.BitSet;
|
||||
+import java.util.function.IntFunction;
|
||||
+
|
||||
+public class ObjectCachingUtils {
|
||||
+
|
||||
+ private static final IntFunction<BitSet> bitSetConstructor = BitSet::new;
|
||||
+
|
||||
+ public static ThreadLocal<Int2ObjectOpenHashMap<BitSet>> BITSETS = ThreadLocal.withInitial(Int2ObjectOpenHashMap::new);
|
||||
+
|
||||
+ private ObjectCachingUtils() {
|
||||
+ }
|
||||
+
|
||||
+ public static BitSet getCachedOrNewBitSet(int bits) {
|
||||
+ final BitSet bitSet = BITSETS.get().computeIfAbsent(bits, bitSetConstructor);
|
||||
+ bitSet.clear();
|
||||
+ return bitSet;
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/com/ishland/c2me/opts/allocs/common/PooledFeatureContext.java b/src/main/java/com/ishland/c2me/opts/allocs/common/PooledFeatureContext.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4c84006c90bda4849b27879d5218f98e6d98f1dc
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/ishland/c2me/opts/allocs/common/PooledFeatureContext.java
|
||||
@@ -0,0 +1,68 @@
|
||||
+package com.ishland.c2me.opts.allocs.common;
|
||||
+
|
||||
+import java.util.Optional;
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+import net.minecraft.util.RandomSource;
|
||||
+import net.minecraft.world.level.WorldGenLevel;
|
||||
+import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
+import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
|
||||
+import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
|
||||
+import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
+
|
||||
+public class PooledFeatureContext<FC extends FeatureConfiguration> extends FeaturePlaceContext<FC> {
|
||||
+
|
||||
+ public static final ThreadLocal<SimpleObjectPool<PooledFeatureContext<?>>> POOL = ThreadLocal.withInitial(() -> new SimpleObjectPool<>(unused -> new PooledFeatureContext<>(), unused -> {}, 2048));
|
||||
+
|
||||
+ private Optional<ConfiguredFeature<?, ?>> feature;
|
||||
+ private WorldGenLevel world;
|
||||
+ private ChunkGenerator generator;
|
||||
+ private RandomSource random;
|
||||
+ private BlockPos origin;
|
||||
+ private FC config;
|
||||
+
|
||||
+ public PooledFeatureContext() {
|
||||
+ super(null, null, null, null, null, null);
|
||||
+ }
|
||||
+
|
||||
+ public void reInit(Optional<ConfiguredFeature<?, ?>> feature, WorldGenLevel world, ChunkGenerator generator, RandomSource random, BlockPos origin, FC config) {
|
||||
+ this.feature = feature;
|
||||
+ this.world = world;
|
||||
+ this.generator = generator;
|
||||
+ this.random = random;
|
||||
+ this.origin = origin;
|
||||
+ this.config = config;
|
||||
+ }
|
||||
+
|
||||
+ public void reInit() {
|
||||
+ this.feature = null;
|
||||
+ this.world = null;
|
||||
+ this.generator = null;
|
||||
+ this.random = null;
|
||||
+ this.origin = null;
|
||||
+ this.config = null;
|
||||
+ }
|
||||
+
|
||||
+ public WorldGenLevel level() {
|
||||
+ return this.world;
|
||||
+ }
|
||||
+
|
||||
+ public ChunkGenerator chunkGenerator() {
|
||||
+ return this.generator;
|
||||
+ }
|
||||
+
|
||||
+ public RandomSource random() {
|
||||
+ return this.random;
|
||||
+ }
|
||||
+
|
||||
+ public BlockPos origin() {
|
||||
+ return this.origin;
|
||||
+ }
|
||||
+
|
||||
+ public FC config() {
|
||||
+ return this.config;
|
||||
+ }
|
||||
+
|
||||
+ public Optional<ConfiguredFeature<?, ?>> topFeature() {
|
||||
+ return this.feature;
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/main/java/com/ishland/c2me/opts/allocs/common/SimpleObjectPool.java b/src/main/java/com/ishland/c2me/opts/allocs/common/SimpleObjectPool.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b989019847f73ba3af57f7428699c9c869d6332f
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/ishland/c2me/opts/allocs/common/SimpleObjectPool.java
|
||||
@@ -0,0 +1,57 @@
|
||||
+package com.ishland.c2me.opts.allocs.common;
|
||||
+
|
||||
+import com.google.common.base.Preconditions;
|
||||
+
|
||||
+import java.util.Objects;
|
||||
+import java.util.function.Consumer;
|
||||
+import java.util.function.Function;
|
||||
+
|
||||
+public class SimpleObjectPool<T> {
|
||||
+
|
||||
+ private final Function<SimpleObjectPool<T>, T> constructor;
|
||||
+ private final Consumer<T> initializer;
|
||||
+ private final int size;
|
||||
+
|
||||
+ private final Object[] cachedObjects;
|
||||
+ private int allocatedCount = 0;
|
||||
+
|
||||
+ public SimpleObjectPool(Function<SimpleObjectPool<T>, T> constructor, Consumer<T> initializer, int size) {
|
||||
+ this.constructor = Objects.requireNonNull(constructor);
|
||||
+ this.initializer = Objects.requireNonNull(initializer);
|
||||
+ Preconditions.checkArgument(size > 0);
|
||||
+ this.cachedObjects = new Object[size];
|
||||
+ this.size = size;
|
||||
+
|
||||
+ for (int i = 0; i < size; i++) {
|
||||
+ final T object = constructor.apply(this);
|
||||
+ this.cachedObjects[i] = object;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public T alloc() {
|
||||
+ final T object;
|
||||
+ synchronized (this) {
|
||||
+ if (this.allocatedCount >= this.size) { // oversized, falling back to normal alloc
|
||||
+ object = this.constructor.apply(this);
|
||||
+ return object;
|
||||
+ }
|
||||
+
|
||||
+ // get an object from the array
|
||||
+ final int ordinal = this.allocatedCount++;
|
||||
+ object = (T) this.cachedObjects[ordinal];
|
||||
+ this.cachedObjects[ordinal] = null;
|
||||
+ }
|
||||
+
|
||||
+ this.initializer.accept(object); // initialize the object
|
||||
+
|
||||
+ return object;
|
||||
+ }
|
||||
+
|
||||
+ public void release(T object) {
|
||||
+ synchronized (this) {
|
||||
+ if (this.allocatedCount == 0) return; // pool is full
|
||||
+ this.cachedObjects[--this.allocatedCount] = object; // store the object into the pool
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+}
|
||||
diff --git a/src/main/java/net/minecraft/resources/ResourceLocation.java b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
index 7017dd42f832d928f1008a05f01701667d951644..4e767dd8f9594e8a8f5d71e2bfd8c976c0032f98 100644
|
||||
--- a/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
+++ b/src/main/java/net/minecraft/resources/ResourceLocation.java
|
||||
@@ -27,6 +27,7 @@ public class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
public static final String REALMS_NAMESPACE = "realms";
|
||||
protected final String namespace;
|
||||
protected final String path;
|
||||
+ private String cachedString = null; // Mirai - c2me: opts allocs
|
||||
|
||||
protected ResourceLocation(String[] id) {
|
||||
this.namespace = StringUtils.isEmpty(id[0]) ? "minecraft" : id[0];
|
||||
@@ -99,7 +100,16 @@ public class ResourceLocation implements Comparable<ResourceLocation> {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
- return this.namespace + ":" + this.path;
|
||||
+ // Mirai start - c2me: opts allocs
|
||||
+ /**
|
||||
+ * @author ishland
|
||||
+ * @reason cache toString
|
||||
+ */
|
||||
+ if (this.cachedString != null) return this.cachedString;
|
||||
+ final String s = this.namespace + ":" + this.path;
|
||||
+ this.cachedString = s;
|
||||
+ return s;
|
||||
+ // Mirai end
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredFeature.java
|
||||
index 2f67705132df06ae6231dd1b89a4f61a90616ef5..1013df19df55316200169f6c3deec8876ea4686a 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredFeature.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/ConfiguredFeature.java
|
||||
@@ -12,6 +12,10 @@ import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.level.WorldGenLevel;
|
||||
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
|
||||
+// Mirai start - c2me: opts allocs
|
||||
+import com.ishland.c2me.opts.allocs.common.PooledFeatureContext;
|
||||
+import com.ishland.c2me.opts.allocs.common.SimpleObjectPool;
|
||||
+// Mirai end
|
||||
|
||||
public record ConfiguredFeature<FC extends FeatureConfiguration, F extends Feature<FC>>(F feature, FC config) {
|
||||
public static final Codec<ConfiguredFeature<?, ?>> DIRECT_CODEC = Registry.FEATURE.byNameCodec().dispatch((configuredFeature) -> {
|
||||
@@ -21,7 +25,22 @@ public record ConfiguredFeature<FC extends FeatureConfiguration, F extends Featu
|
||||
public static final Codec<HolderSet<ConfiguredFeature<?, ?>>> LIST_CODEC = RegistryCodecs.homogeneousList(Registry.CONFIGURED_FEATURE_REGISTRY, DIRECT_CODEC);
|
||||
|
||||
public boolean place(WorldGenLevel world, ChunkGenerator chunkGenerator, RandomSource random, BlockPos origin) {
|
||||
- return this.feature.place(this.config, world, chunkGenerator, random, origin);
|
||||
+ // Mirai start - c2me: opts allocs
|
||||
+ /**
|
||||
+ * @author ishland
|
||||
+ * @reason pool FeatureContext
|
||||
+ */
|
||||
+ if (!world.ensureCanWrite(origin)) return false;
|
||||
+ final SimpleObjectPool<PooledFeatureContext<?>> pool = PooledFeatureContext.POOL.get();
|
||||
+ final PooledFeatureContext<FC> context = (PooledFeatureContext<FC>) pool.alloc();
|
||||
+ try {
|
||||
+ context.reInit(java.util.Optional.empty(), world, chunkGenerator, random, origin, this.config);
|
||||
+ return this.feature.place(context);
|
||||
+ } finally {
|
||||
+ context.reInit();
|
||||
+ pool.release(context);
|
||||
+ }
|
||||
+ // Mirai end
|
||||
}
|
||||
|
||||
public Stream<ConfiguredFeature<?, ?>> getFeatures() {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java b/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java
|
||||
index b2f36a998437e2a63a3cbc6c3aa95b1402bff2f1..d69a57f67eeb99f3db4f80d13b9f0276ce4603af 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/levelgen/feature/OreFeature.java
|
||||
@@ -54,7 +54,7 @@ public class OreFeature extends Feature<OreConfiguration> {
|
||||
|
||||
protected boolean doPlace(WorldGenLevel world, RandomSource randomSource, OreConfiguration config, double startX, double endX, double startZ, double endZ, double startY, double endY, int x, int y, int z, int horizontalSize, int verticalSize) {
|
||||
int i = 0;
|
||||
- BitSet bitSet = new BitSet(horizontalSize * verticalSize * horizontalSize);
|
||||
+ BitSet bitSet = com.ishland.c2me.opts.allocs.common.ObjectCachingUtils.getCachedOrNewBitSet(horizontalSize * verticalSize * horizontalSize); // Mirai - c2me: opts allocs
|
||||
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||
int j = config.size;
|
||||
double[] ds = new double[j * 4];
|
||||
Reference in New Issue
Block a user