Add more patches back

This commit is contained in:
Arthur Blanchot
2022-06-28 21:25:08 +02:00
parent f0c1c0f5f0
commit 0750e5fe34
32 changed files with 1213 additions and 38 deletions

View 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) {

View 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();

View 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()) {

View File

@@ -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

View 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() {

View 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];