Compare commits

...

8 Commits

Author SHA1 Message Date
Helvetica Volubi 106f1edb09 set release to stable cannel 2026-07-28 15:38:35 +08:00
Helvetica Volubi eea830188f update some optimizations from upstream 2026-07-28 15:37:41 +08:00
Helvetica Volubi f517cc0b8a feat: update b_linear format from upstream
Because of some reasons, this patch will be anonymous and hide the original commit address.
2026-07-28 02:03:00 +08:00
Helvetica Volubi d90c8567d3 [ci skip] simplify code 2026-07-28 01:29:59 +08:00
Helvetica Volubi 78b3a8a6e7 [ci skip] Use ComfreyWeight instead of HyacinthusWeight 2026-07-27 03:43:02 +08:00
Helvetica Volubi 2f93769135 [ci skip] Use ComfreyWeight instead of HyacinthusWeight 2026-07-27 03:32:49 +08:00
Helvetica Volubi 4e277ad91e [ci skip] Update clip version 2026-07-27 01:17:13 +08:00
Helvetica Volubi 1620687dba [ci skip] fix typo 2026-07-26 19:09:05 +08:00
48 changed files with 3300 additions and 1598 deletions
+1 -1
View File
@@ -90,7 +90,7 @@ java {
<dependency>
<groupId>fun.bm.lophine</groupId>
<artifactId>lophine-api</artifactId>
<version>[26.1.2.build,)</version>
<version>[26.2.build,)</version>
</dependency>
</dependencies>
```
+1 -1
View File
@@ -89,7 +89,7 @@ java {
<dependency>
<groupId>fun.bm.lophine</groupId>
<artifactId>lophine-api</artifactId>
<version>[26.1.2.build,)</version>
<version>[26.2.build,)</version>
<scope>provided</scope>
</dependency>
</dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent
plugins {
java // TODO java launcher tasks
id("moe.luminolmc.hyacinthusweight.patcher")
id("fun.bm.comfreyweight.patcher")
}
paperweight {
+4 -4
View File
@@ -1,11 +1,11 @@
group=fun.bm.lophine
mcVersion=26.2
apiVersion=26.2
channel=BETA
clipVersion=1.0.0
weightVersion=2.0.15
channel=STABLE
clipVersion=1.0.1
weightVersion=1.0.0
# true for release, false for skip release, pre for pre-release
release=pre
release=true
# true for push to repo, false for skip push repo, auto for detect by release value
pushRepo=auto
+2 -2
View File
@@ -5,7 +5,7 @@
`maven-publish`
idea
- id("io.papermc.paperweight.core")
+ id("moe.luminolmc.hyacinthusweight.core") // TODO Later - rebrand
+ id("fun.bm.comfreyweight.core")
id("io.papermc.fill.gradle") version "1.0.12"
}
@@ -15,7 +15,7 @@
dependencies {
mache("io.papermc:mache:26.2+build.1")
- paperclip("io.papermc:paperclip:3.0.4")
+ hyacinthusclip("fun.bm:morninggloryclip:${providers.gradleProperty("clipVersion").get()}") // TODO Later - rebrand
+ morninggloryclip("fun.bm:morninggloryclip:${providers.gradleProperty("clipVersion").get()}")
}
paperweight {
@@ -1,11 +1,14 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sun, 28 Jun 2026 18:54:50 +0800
Subject: [PATCH] Configurable region format framework
Subject: [PATCH] Anonymous Object: Configurable region format framework
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
index a814512fcfb85312474ae2c2c21443843bf57831..2e084a5b28cbe4737f48c25e10af589213525362 100644
index a814512fcfb85312474ae2c2c21443843bf57831..9d69a022872e06b320bee46329cd8889f74fbbaa 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/ChunkSystemRegionFileStorage.java
@@ -8,9 +8,9 @@ public interface ChunkSystemRegionFileStorage {
@@ -13,15 +16,15 @@ index a814512fcfb85312474ae2c2c21443843bf57831..2e084a5b28cbe4737f48c25e10af5892
public boolean moonrise$doesRegionFileNotExistNoIO(final int chunkX, final int chunkZ);
- public RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ);
+ public abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ); // Luminol - Configurable region file format
+ public io.anonymous.anonymous.data.RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ); // Anonymous - Configurable region file format
- public RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException;
+ public abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException; // Luminol - Configurable region file format
+ public io.anonymous.anonymous.data.RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException; // Anonymous - Configurable region file format
public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(
final int chunkX, final int chunkZ, final CompoundTag compound
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
index 3bb9b58ee97464687e348e23b99159226415c267..fc264727141c3897e6c06819b9713d4f6395baf0 100644
index 3bb9b58ee97464687e348e23b99159226415c267..4c3ad63f17bb4a04f982b36ad3f53d3c0f58bdb5 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/io/MoonriseRegionFileIO.java
@@ -1273,7 +1273,7 @@ public final class MoonriseRegionFileIO {
@@ -29,7 +32,7 @@ index 3bb9b58ee97464687e348e23b99159226415c267..fc264727141c3897e6c06819b9713d4f
// Paper start - flush regionfiles on save
if (this.world.paperConfig().chunks.flushRegionsOnSave) {
- final RegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ);
+ final abomination.IRegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ); // Luminol - Add configurable region file
+ final io.anonymous.anonymous.data.RegionFile regionFile = this.regionDataController.getCache().moonrise$getRegionFileIfLoaded(this.chunkX, this.chunkZ); // Anonymous - Configurable region file format
if (regionFile != null) {
regionFile.flush();
} // else: evicted from cache, which should have called flush
@@ -38,12 +41,12 @@ index 3bb9b58ee97464687e348e23b99159226415c267..fc264727141c3897e6c06819b9713d4f
public static interface IORunnable {
- public void run(final RegionFile regionFile) throws IOException;
+ public void run(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
+ public void run(final io.anonymous.anonymous.data.RegionFile regionFile) throws IOException; // Anonymous - Configurable region file format
}
}
diff --git a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
index 51c126735ace8fdde89ad97b5cab62f244212db0..c7d4d944eb198ac53a3eeae717a25c7d5815c8c1 100644
index 51c126735ace8fdde89ad97b5cab62f244212db0..ea2f45964fb8c617f90938597c230b50d83744aa 100644
--- a/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
+++ b/ca/spottedleaf/moonrise/patches/chunk_system/storage/ChunkSystemChunkBuffer.java
@@ -8,5 +8,5 @@ public interface ChunkSystemChunkBuffer {
@@ -51,10 +54,10 @@ index 51c126735ace8fdde89ad97b5cab62f244212db0..c7d4d944eb198ac53a3eeae717a25c7d
public void moonrise$setWriteOnClose(final boolean value);
- public void moonrise$write(final RegionFile regionFile) throws IOException;
+ public void moonrise$write(final abomination.IRegionFile regionFile) throws IOException; // Luminol - Configurable region file format
+ public void moonrise$write(final io.anonymous.anonymous.data.RegionFile regionFile) throws IOException; // Anonymous - Configurable region file format
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index a49c46eb7df50fc3c5587a2c3668ab6edc887107..83b9aab16124ddcc416f7b4cd95084e1c64fe5b7 100644
index a49c46eb7df50fc3c5587a2c3668ab6edc887107..c74f76b46259204b33b69ad08bb03c81b8b36961 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -986,10 +986,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -62,16 +65,16 @@ index a49c46eb7df50fc3c5587a2c3668ab6edc887107..83b9aab16124ddcc416f7b4cd95084e1
for (ServerLevel level : this.getAllLevels()) {
String storageName = level.getChunkSource().chunkMap.getStorageName();
- LOGGER.info("ThreadedAnvilChunkStorage ({}): All chunks are saved", LEGACY_WORLD_NAMES_FOR_REALMS_LOG.getOrDefault(storageName, storageName));
+ LOGGER.info("ThreadedChunkStorage ({}): All chunks are saved", LEGACY_WORLD_NAMES_FOR_REALMS_LOG.getOrDefault(storageName, storageName)); // Luminol - configurable region format
+ LOGGER.info("ThreadedChunkStorage ({}): All chunks are saved", LEGACY_WORLD_NAMES_FOR_REALMS_LOG.getOrDefault(storageName, storageName)); // Anonymous - Configurable region format
}
- LOGGER.info("ThreadedAnvilChunkStorage: All dimensions are saved");
+ LOGGER.info("ThreadedChunkStorage: All dimensions are saved"); // Luminol - configurable region format
+ LOGGER.info("ThreadedChunkStorage: All dimensions are saved"); // Anonymous - configurable region format
}
return result;
diff --git a/net/minecraft/util/worldupdate/FileToUpgrade.java b/net/minecraft/util/worldupdate/FileToUpgrade.java
index a7f2cfa9277c898038f6b9e0a3401db51012b64c..db4dba8849eb27f8f84acc3297e342da4700d839 100644
index a7f2cfa9277c898038f6b9e0a3401db51012b64c..7b96f3ec2738875a3ed7aa34347c0f174b6579c5 100644
--- a/net/minecraft/util/worldupdate/FileToUpgrade.java
+++ b/net/minecraft/util/worldupdate/FileToUpgrade.java
@@ -4,5 +4,5 @@ import java.util.List;
@@ -79,10 +82,10 @@ index a7f2cfa9277c898038f6b9e0a3401db51012b64c..db4dba8849eb27f8f84acc3297e342da
import net.minecraft.world.level.chunk.storage.RegionFile;
-public record FileToUpgrade(RegionFile file, List<ChunkPos> chunksToUpgrade) {
+public record FileToUpgrade(abomination.IRegionFile file, List<ChunkPos> chunksToUpgrade) { // Luminol - Configurable region file format
+public record FileToUpgrade(io.anonymous.anonymous.data.RegionFile file, List<ChunkPos> chunksToUpgrade) { // Anonymous - Configurable region file format
}
diff --git a/net/minecraft/util/worldupdate/RegionStorageUpgrader.java b/net/minecraft/util/worldupdate/RegionStorageUpgrader.java
index b228cd6c54e8c8998923ab332882d99092769c67..140ef4959fa2fe5b9cd251955c93683e8e69d5ba 100644
index b228cd6c54e8c8998923ab332882d99092769c67..2dd3d0afd8f58e5e68a361dd38c95da06b4d133b 100644
--- a/net/minecraft/util/worldupdate/RegionStorageUpgrader.java
+++ b/net/minecraft/util/worldupdate/RegionStorageUpgrader.java
@@ -36,7 +36,7 @@ import org.slf4j.Logger;
@@ -90,7 +93,7 @@ index b228cd6c54e8c8998923ab332882d99092769c67..140ef4959fa2fe5b9cd251955c93683e
private static final Logger LOGGER = LogUtils.getLogger();
private static final String NEW_DIRECTORY_PREFIX = "new_";
- private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$");
+ private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\." + me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getArgument() + "$"); // Luminol - Configurable region file format
+ private static final Pattern REGEX = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\." + me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getArgument() + "$"); // Anonymous - Configurable region file format
private final DataFixer dataFixer;
private final UpgradeProgress upgradeProgress;
private final String type;
@@ -99,8 +102,8 @@ index b228cd6c54e8c8998923ab332882d99092769c67..140ef4959fa2fe5b9cd251955c93683e
List<ChunkPos> chunkPositions = Lists.newArrayList();
- try (RegionFile regionSource = new RegionFile(info, regionFile.toPath(), regionFolder, true)) {
+ var regionFileInfo = new me.earthme.luminol.utils.RegionCreatorInfo(info, regionFile.toPath(), regionFolder, true); // Luminol - Configurable region file format
+ try (abomination.IRegionFile regionSource = me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getCreator().create(regionFileInfo)) { // Luminol - Configurable region file format
+ var regionFileInfo = new io.anonymous.anonymous.utils.RegionCreatorInfo(info, regionFile.toPath(), regionFolder, true); // Anonymous - Configurable region file format
+ try (io.anonymous.anonymous.data.RegionFile regionSource = me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getCreator().newFile(regionFileInfo)) { // Anonymous - Configurable region file format
for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) {
ChunkPos pos = new ChunkPos(x + xOffset, z + zOffset);
@@ -109,12 +112,12 @@ index b228cd6c54e8c8998923ab332882d99092769c67..140ef4959fa2fe5b9cd251955c93683e
}
- private void onFileFinished(final RegionFile regionFile) {
+ private void onFileFinished(final abomination.IRegionFile regionFile) { // Luminol - Configurable region file format
+ private void onFileFinished(final io.anonymous.anonymous.data.RegionFile regionFile) { // Anonymous - Configurable region file format
if (this.recreateRegionFiles) {
if (this.previousWriteFuture != null) {
this.previousWriteFuture.join();
diff --git a/net/minecraft/world/level/chunk/storage/RegionFile.java b/net/minecraft/world/level/chunk/storage/RegionFile.java
index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93addb767392 100644
index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..821924f85a507589a039832be8657e1dc3c0ce0c 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -22,7 +22,7 @@ import net.minecraft.world.level.ChunkPos;
@@ -122,7 +125,7 @@ index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93ad
import org.slf4j.Logger;
-public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile { // Paper - rewrite chunk system
+public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile , abomination.IRegionFile{ // Paper - rewrite chunk system // Luminol - Configurable region file format
+public class RegionFile implements AutoCloseable, ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile , io.anonymous.anonymous.data.RegionFile{ // Paper - rewrite chunk system // Anonymous - Configurable region file format
private static final Logger LOGGER = LogUtils.getLogger();
public static final int MAX_CHUNK_SIZE = 500 * 1024 * 1024; // Paper - don't write garbage data to disk if writing serialization fails
private static final int SECTOR_BYTES = 4096;
@@ -131,7 +134,7 @@ index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93ad
}
- boolean recalculateHeader() throws IOException {
+ public boolean recalculateHeader() throws IOException { // Luminol - Configurable region file format
+ public boolean recalculateHeader() throws IOException { // Anonymous - Configurable region file format
if (!this.canRecalcHeader) {
return false;
}
@@ -140,7 +143,7 @@ index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93ad
}
- protected synchronized void write(final ChunkPos pos, final ByteBuffer data) throws IOException {
+ public synchronized void write(final ChunkPos pos, final ByteBuffer data) throws IOException { // Luminol - Configurable region file format
+ public synchronized void write(final ChunkPos pos, final ByteBuffer data) throws IOException { // Anonymous - Configurable region file format
int offsetIndex = getOffsetIndex(pos);
int offset = this.offsets.get(offsetIndex);
int sectorNumber = getSectorNumber(offset);
@@ -149,7 +152,7 @@ index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93ad
@Override
- public final void moonrise$write(final RegionFile regionFile) throws IOException {
+ public final void moonrise$write(final abomination.IRegionFile regionFile) throws IOException { // Luminol - Configurable region file format
+ public final void moonrise$write(final io.anonymous.anonymous.data.RegionFile regionFile) throws IOException { // Anonymous - Configurable region file format
regionFile.write(this.pos, ByteBuffer.wrap(this.buf, 0, this.count));
}
// Paper end - rewrite chunk system
@@ -158,12 +161,12 @@ index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93ad
}
- synchronized boolean isOversized(int x, int z) {
+ public synchronized boolean isOversized(int x, int z) { // Luminol - Configurable region file format
+ public synchronized boolean isOversized(int x, int z) { // Anonymous - Configurable region file format
return this.oversized[getChunkIndex(x, z)] == 1;
}
- synchronized void setOversized(int x, int z, boolean oversized) throws IOException {
+ public synchronized void setOversized(int x, int z, boolean oversized) throws IOException { // Luminol - Configurable region file format
+ public synchronized void setOversized(int x, int z, boolean oversized) throws IOException { // Anonymous - Configurable region file format
final int offset = getChunkIndex(x, z);
boolean previous = this.oversized[offset] == 1;
this.oversized[offset] = (byte) (oversized ? 1 : 0);
@@ -172,12 +175,12 @@ index 3de7fd2b084c38e72d7a6bc416880a881f514ad3..d3350dee1d6d5bc15dcdfba3611f93ad
}
- synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException {
+ public synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException { // Luminol - Configurable region file format
+ public synchronized net.minecraft.nbt.CompoundTag getOversizedData(int x, int z) throws IOException { // Anonymous - Configurable region file format
Path file = getOversizedFile(x, z);
try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new java.util.zip.InflaterInputStream(Files.newInputStream(file))))) {
return net.minecraft.nbt.NbtIo.read((java.io.DataInput) out);
diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977ebfb18517 100644
index 63b40c420030d935bb81a219fb33defe0946e21f..e0e19f091f6b85d7788259cfcc53cc3db848b68e 100644
--- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -19,7 +19,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise
@@ -185,7 +188,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
public static final String ANVIL_EXTENSION = ".mca";
private static final int MAX_CACHE_SIZE = 256;
- private final Long2ObjectLinkedOpenHashMap<RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>();
+ private final Long2ObjectLinkedOpenHashMap<abomination.IRegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>(); // Luminol - Configurable region file format
+ private final Long2ObjectLinkedOpenHashMap<io.anonymous.anonymous.data.RegionFile> regionCache = new Long2ObjectLinkedOpenHashMap<>(); // Anonymous - Configurable region file format
private final RegionStorageInfo info;
private final Path folder;
private final boolean sync;
@@ -194,7 +197,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
public static ChunkPos getRegionFileCoordinates(Path file) {
String fileName = file.getFileName().toString();
- if (!fileName.startsWith("r.") || !fileName.endsWith(".mca")) {
+ if (!fileName.startsWith("r.") || !fileName.endsWith(getExtensionName())) { // Luminol - Configurable region file format
+ if (!fileName.startsWith("r.") || !fileName.endsWith(getExtensionName())) { // Anonymous - Configurable region file format
return null;
}
@@ -203,32 +206,32 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
private final it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet nonExistingRegionFiles = new it.unimi.dsi.fastutil.longs.LongLinkedOpenHashSet();
private static String getRegionFileName(final int chunkX, final int chunkZ) {
- return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + ".mca";
+ return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + getExtensionName(); // Luminol - Configurable region file format
+ return "r." + (chunkX >> REGION_SHIFT) + "." + (chunkZ >> REGION_SHIFT) + getExtensionName(); // Anonymous - Configurable region file format
}
+ // Luminol start - Configurable region file format
+ public static abomination.IRegionFile createNew(RegionStorageInfo info, Path filePath, Path folder, boolean sync) throws IOException{
+ final me.earthme.luminol.enums.EnumRegionFormat regionFormat = me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat;
+ // Anonymous start - Configurable region file format
+ public static io.anonymous.anonymous.data.RegionFile createNew(RegionStorageInfo info, Path filePath, Path folder, boolean sync) throws IOException{
+ final io.anonymous.anonymous.enums.EnumRegionFormat regionFormat = me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat;
+ final String fullFileName = filePath.getFileName().toString();
+ final String[] fullNameSplit = fullFileName.split("\\.");
+ final String extensionName = fullNameSplit[fullNameSplit.length - 1];
+
+ if (!regionFormat.getArgument().equalsIgnoreCase(extensionName)) {
+ // delayed crash
+ // raise a delayed crash
+ io.papermc.paper.threadedregions.RegionizedServer.getInstance().addTask(() -> {
+ new RuntimeException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
+ throw new RuntimeException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
+ });
+
+
+ throw new IOException("Invalid region file format: " + extensionName + " expected " + regionFormat.getArgument());
+ }
+
+ return regionFormat.getCreator().create(new me.earthme.luminol.utils.RegionCreatorInfo(info, filePath, folder, sync));
+ return regionFormat.getCreator().newFile(new io.anonymous.anonymous.utils.RegionCreatorInfo(info, filePath, folder, sync));
+ }
+
+ public static String getExtensionName() {
+ return "." + me.earthme.luminol.config.modules.function.RegionFormatConfig.regionFormat.getArgument();
+ }
+ // Luminol end
+ // Anonymous end
private boolean doesRegionFilePossiblyExist(final long position) {
synchronized (this.nonExistingRegionFiles) {
@@ -237,17 +240,17 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
@Override
- public synchronized final RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) {
+ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) { // Luminol - Configurable region file format
+ public synchronized final io.anonymous.anonymous.data.RegionFile moonrise$getRegionFileIfLoaded(final int chunkX, final int chunkZ) { // Anonymous - Configurable region file format
return this.regionCache.getAndMoveToFirst(ChunkPos.pack(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT));
}
@Override
- public synchronized final RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException {
+ public synchronized final abomination.IRegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException { // Luminol - Configurable region file format
+ public synchronized final io.anonymous.anonymous.data.RegionFile moonrise$getRegionFileIfExists(final int chunkX, final int chunkZ) throws IOException { // Anonymous - Configurable region file format
final long key = ChunkPos.pack(chunkX >> REGION_SHIFT, chunkZ >> REGION_SHIFT);
- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
+ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
+ io.anonymous.anonymous.data.RegionFile ret = this.regionCache.getAndMoveToFirst(key); // Anonymous - Configurable region file format
if (ret != null) {
return ret;
}
@@ -256,7 +259,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
FileUtil.createDirectoriesSafe(this.folder);
- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Anonymous - Configurable region file format
this.regionCache.putAndMoveToFirst(key, ret);
@@ -265,7 +268,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
- final RegionFile regionFile = this.getRegionFile(pos);
+ final abomination.IRegionFile regionFile = this.getRegionFile(pos); // Luminol - Configurable region file format
+ final io.anonymous.anonymous.data.RegionFile regionFile = this.getRegionFile(pos); // Anonymous - Configurable region file format
// note: not required to keep regionfile loaded after this call, as the write param takes a regionfile as input
// (and, the regionfile parameter is unused for writing until the write call)
@@ -274,7 +277,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
if (writeData.result() == ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.DELETE) {
- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
+ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
+ final io.anonymous.anonymous.data.RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Anonymous - Configurable region file format
if (regionFile != null) {
regionFile.clear(pos);
} // else: didn't exist
@@ -283,7 +286,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
final int chunkX, final int chunkZ
) throws IOException {
- final RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ);
+ final abomination.IRegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Luminol - Configurable region file format
+ final io.anonymous.anonymous.data.RegionFile regionFile = this.moonrise$getRegionFileIfExists(chunkX, chunkZ); // Anonymous - Configurable region file format
final DataInputStream input = regionFile == null ? null : regionFile.getChunkDataInputStream(new ChunkPos(chunkX, chunkZ));
@@ -292,7 +295,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
final ChunkPos pos = new ChunkPos(chunkX, chunkZ);
final ChunkPos headerChunkPos = SerializableChunkData.getChunkCoordinate(ret);
- final RegionFile regionFile = this.getRegionFile(pos);
+ final abomination.IRegionFile regionFile = this.getRegionFile(pos); // Luminol - Configurable region file format
+ final io.anonymous.anonymous.data.RegionFile regionFile = this.getRegionFile(pos); // Anonymous - Configurable region file format
if (regionFile.getRecalculateCount() != readData.recalculateCount()) {
return null;
@@ -301,7 +304,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
// Paper end - rewrite chunk system
// Paper start - rewrite chunk system
- public RegionFile getRegionFile(ChunkPos pos) throws IOException {
+ public abomination.IRegionFile getRegionFile(ChunkPos pos) throws IOException { // Luminol - Configurable region file format
+ public io.anonymous.anonymous.data.RegionFile getRegionFile(ChunkPos pos) throws IOException { // Anonymous - Configurable region file format
return this.getRegionFile(pos, false);
}
// Paper end - rewrite chunk system
@@ -310,7 +313,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
}
- @org.jetbrains.annotations.Contract("_, false -> !null") private @Nullable RegionFile getRegionFile(final ChunkPos pos, boolean existingOnly) throws IOException { // CraftBukkit
+ @org.jetbrains.annotations.Contract("_, false -> !null") private abomination.@Nullable IRegionFile getRegionFile(final ChunkPos pos, boolean existingOnly) throws IOException { // CraftBukkit // Luminol - Configurable region file format
+ @org.jetbrains.annotations.Contract("_, false -> !null") private io.anonymous.anonymous.data.RegionFile getRegionFile(final ChunkPos pos, boolean existingOnly) throws IOException { // CraftBukkit // Anonymous - Configurable region file format
// Paper start - rewrite chunk system
if (existingOnly) {
return this.moonrise$getRegionFileIfExists(pos.x(), pos.z());
@@ -319,7 +322,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
final long key = ChunkPos.pack(pos.x() >> REGION_SHIFT, pos.z() >> REGION_SHIFT);
- RegionFile ret = this.regionCache.getAndMoveToFirst(key);
+ abomination.IRegionFile ret = this.regionCache.getAndMoveToFirst(key); // Luminol - Configurable region file format
+ io.anonymous.anonymous.data.RegionFile ret = this.regionCache.getAndMoveToFirst(key); // Anonymous - Configurable region file format
if (ret != null) {
return ret;
}
@@ -328,7 +331,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
FileUtil.createDirectoriesSafe(this.folder);
- ret = new RegionFile(this.info, regionPath, this.folder, this.sync);
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Luminol - Configurable region file format
+ ret = this.createNew(this.info, regionPath, this.folder, this.sync); // Anonymous - Configurable region file format
this.regionCache.putAndMoveToFirst(key, ret);
@@ -337,7 +340,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
}
- private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException {
+ private static CompoundTag readOversizedChunk(abomination.IRegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { // Luminol - Configurable region file format
+ private static CompoundTag readOversizedChunk(io.anonymous.anonymous.data.RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { // Anonymous - Configurable region file format
synchronized (regionfile) {
try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x(), chunkCoordinate.z());
@@ -346,7 +349,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
public @Nullable CompoundTag read(final ChunkPos pos) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
- RegionFile region = this.getRegionFile(pos, true);
+ abomination.IRegionFile region = this.getRegionFile(pos, true); // Luminol - Configurable region file format
+ io.anonymous.anonymous.data.RegionFile region = this.getRegionFile(pos, true); // Anonymous - Configurable region file format
if (region == null) {
return null;
}
@@ -355,7 +358,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
public void scanChunk(final ChunkPos pos, final StreamTagVisitor scanner) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
- RegionFile region = this.getRegionFile(pos, true);
+ abomination.IRegionFile region = this.getRegionFile(pos, true); // Luminol - Configurable region file format
+ io.anonymous.anonymous.data.RegionFile region = this.getRegionFile(pos, true); // Anonymous - Configurable region file format
if (region == null) {
return;
}
@@ -364,7 +367,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
public void write(final ChunkPos pos, final @Nullable CompoundTag value) throws IOException {
if (!SharedConstants.DEBUG_DONT_SAVE_WORLD) {
- RegionFile region = this.getRegionFile(pos, value == null); // CraftBukkit // Paper - rewrite chunk system
+ abomination.IRegionFile region = this.getRegionFile(pos, value == null); // CraftBukkit // Paper - rewrite chunk system // Luminol - Configurable region file format
+ io.anonymous.anonymous.data.RegionFile region = this.getRegionFile(pos, value == null); // CraftBukkit // Paper - rewrite chunk system // Anonymous - Configurable region file format
// Paper start - rewrite chunk system
if (region == null) {
// if the RegionFile doesn't exist, no point in deleting from it
@@ -373,7 +376,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
synchronized (this) {
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();
- for (final RegionFile regionFile : this.regionCache.values()) {
+ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
+ for (final io.anonymous.anonymous.data.RegionFile regionFile : this.regionCache.values()) { // Anonymous - Configurable region file format
try {
regionFile.close();
} catch (final IOException ex) {
@@ -382,7 +385,7 @@ index 63b40c420030d935bb81a219fb33defe0946e21f..2e67e69862cbf5d804de50193442977e
synchronized (this) {
final ExceptionCollector<IOException> exceptionCollector = new ExceptionCollector<>();
- for (final RegionFile regionFile : this.regionCache.values()) {
+ for (final abomination.IRegionFile regionFile : this.regionCache.values()) { // Luminol - Configurable region file format
+ for (final io.anonymous.anonymous.data.RegionFile regionFile : this.regionCache.values()) { // Anonymous - Configurable region file format
try {
regionFile.flush();
} catch (final IOException ex) {
@@ -6,7 +6,7 @@ Subject: [PATCH] Force disable builtin spark plugin
The spark passed down from paper has some memory leaking issue, so we fully removed it from the code to prevent that memory leaking issue.
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 83b9aab16124ddcc416f7b4cd95084e1c64fe5b7..7683c12d48d23dd43bce3d3b5633029c596930a5 100644
index c74f76b46259204b33b69ad08bb03c81b8b36961..cc8364891a5d2196e8809479db984b67b5bcb079 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -672,8 +672,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -228,7 +228,7 @@ index 5a72fa0d72bfdb927293abe921c57f6ae964a6ec..f8344f640f119e3865f2718d1abd0ede
private void uncaughtException(final Thread thread, final Throwable thr) {
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 7683c12d48d23dd43bce3d3b5633029c596930a5..ab61d18845827ac835edf92651d0b510358106ff 100644
index cc8364891a5d2196e8809479db984b67b5bcb079..7c67a8a6cf83ab80d3a8b37c5ff03e7a56497bc9 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -236,7 +236,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -5,7 +5,7 @@ Subject: [PATCH] Add config for server mod name
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index ab61d18845827ac835edf92651d0b510358106ff..d4e31bb829451a687bf567fd0357f46fd7d46902 100644
index 7c67a8a6cf83ab80d3a8b37c5ff03e7a56497bc9..b2823c71ecb5e1f7a3c4c5b9f691d4cdb5419db3 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2072,7 +2072,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -19,7 +19,7 @@ index 9b1dcfadd6d5ae868b087a18983d03e8bb86b56a..21f2b9866e1cf36421e10a945fb6fbaa
DefaultGameModeCommands.register(this.dispatcher);
//DialogCommand.register(this.dispatcher, context); // Folia - region threading - TODO
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index d4e31bb829451a687bf567fd0357f46fd7d46902..4f292468194baae343eeb077362e51dcfb6c0df1 100644
index b2823c71ecb5e1f7a3c4c5b9f691d4cdb5419db3..a82cafadf2136d30ae7bca172062713a651373ac 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2415,6 +2415,16 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -17,7 +17,7 @@ index 52dcbcf64c3a510d4a4524b7d0ee226d9a73511d..051d601e7e809518e8d82ae4ae325905
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 4f292468194baae343eeb077362e51dcfb6c0df1..f0a3fdaf7e9d342b472b3db42f5b59b0f6691b49 100644
index a82cafadf2136d30ae7bca172062713a651373ac..e43aa6daa8d4465764348be5b82be5f163ef0819 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1743,7 +1743,46 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -69,7 +69,7 @@ index f32d118e1e925b2155cef3fcdcb1e194c541e242..2d5d4170e1f45ae9113c37623b406686
// this is copy on write to allow packet processing to iterate safely
private final CopyOnWriteArrayList<ServerPlayer> localPlayers = new CopyOnWriteArrayList<>();
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index f0a3fdaf7e9d342b472b3db42f5b59b0f6691b49..ac49bcc53951c025de0160fd8afd319b1f3d1347 100644
index e43aa6daa8d4465764348be5b82be5f163ef0819..f4274e844018992bba7c32d2146198efc034631e 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1973,6 +1973,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -18,7 +18,7 @@ index aa7931c9b6dc3bba2c8dfecff8df2db302ad905b..c67ea715f02086e5a39cc5832ccdc0b3
WorldBorderCommand.register(this.dispatcher);
if (JvmProfiler.INSTANCE.isAvailable()) {
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index ac49bcc53951c025de0160fd8afd319b1f3d1347..c91902632d0e97b814e387454b119edb62b67413 100644
index f4274e844018992bba7c32d2146198efc034631e..42ee15c813761702031d5a63f0d080b135be2e0f 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -3127,8 +3127,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -8,7 +8,7 @@ A part of Leaf(https://github.com/Winds-Studio/Leaf/blob/edb0504069139beaa6f39ef
License: https://github.com/Winds-Studio/Leaf/blob/edb0504069139beaa6f39efa4702370c2576b3fc/LICENSE.md
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index c91902632d0e97b814e387454b119edb62b67413..4b6f961e695155db1d6cc86496491017bf3a6383 100644
index 42ee15c813761702031d5a63f0d080b135be2e0f..1736816e26c255645d62696814cd539ee1ffed8d 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -217,7 +217,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -48,7 +48,7 @@ index c67ea715f02086e5a39cc5832ccdc0b32199db93..946094713bdb294d7d8beb03967b2a24
SaveOnCommand.register(this.dispatcher);
SetPlayerIdleTimeoutCommand.register(this.dispatcher);
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 4b6f961e695155db1d6cc86496491017bf3a6383..e7f7f7927fc1e2ce45ea5dbf7cc9ec19197c599f 100644
index 1736816e26c255645d62696814cd539ee1ffed8d..a0c285d2cb666d0f9bd0e859e0dac414254325c3 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1652,6 +1652,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -36,7 +36,7 @@ index 08e253662a2c183c0ab53a51cc07485cff33bf2c..1bd678d668a1febc129f4cb4d0d95ea2
};
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index e7f7f7927fc1e2ce45ea5dbf7cc9ec19197c599f..1f13f7b016b4256e92989d83003a983d6ba1c750 100644
index a0c285d2cb666d0f9bd0e859e0dac414254325c3..9614a22c4b67e5e3a46e46fa69d22c136d4beb4b 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -2016,6 +2016,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -33,7 +33,7 @@ index d2e9d46bbd9ee4ce45419b11499d7a7bc50f0219..848967dbe41694411603ef369cfdc3a0
private final java.util.concurrent.atomic.AtomicBoolean disconnectionHandled = new java.util.concurrent.atomic.AtomicBoolean(false); // Folia - region threading - may be called concurrently during configuration stage
private int receivedPackets;
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 1f13f7b016b4256e92989d83003a983d6ba1c750..f76e40f8bbea076ad620f7525d4d8666603a5175 100644
index 9614a22c4b67e5e3a46e46fa69d22c136d4beb4b..5bc6baf2a13b78f65e5851a22ca79dbcaed957b2 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -296,6 +296,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -88,7 +88,7 @@ index 6c05b9276bdc267a36376f6c64592a50e4b2b36e..21d2c97b3d1e1d29c9de02b6acd58985
result.add(player);
if (result.size() >= limit) {
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index f76e40f8bbea076ad620f7525d4d8666603a5175..77bbc527b017c2ac42ebe4638457caf32868e3f6 100644
index 5bc6baf2a13b78f65e5851a22ca79dbcaed957b2..803faa6b80a42d16687ea8b109973938d02f4a36 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1909,7 +1909,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -36,7 +36,7 @@ index 20fa23988efbfb50c664fa48cc823adbe8e6ce58..1a95ccd745f4789225d711ab6fe497c6
throw PacketUtils.makeReportedException(e, this.packet, this.listener);
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 77bbc527b017c2ac42ebe4638457caf32868e3f6..6ba62c5c6af4fc060442de8dfb069d5fe8ac0c69 100644
index 803faa6b80a42d16687ea8b109973938d02f4a36..6c5cdfebb3a362c51b3b940397e10536dc67afc8 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1998,11 +1998,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 28 Jul 2026 15:08:10 +0800
Subject: [PATCH] Anonymous Object: Fix wrong variable passing in
RegionizedWorldData
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index 3a50e625160d0dad6bd8fa534b719087dae7881d..20439c632044ae9b4358bfba309b378b3de98601 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -841,7 +841,7 @@ public final class RegionizedWorldData {
}
public void setTickingBlockEntities(final boolean to) {
- this.tickingBlockEntities = true;
+ this.tickingBlockEntities = to; // Anonymous - Fix wrong variable passing in RegionizedWorldData
}
public List<TickingBlockEntity> getBlockEntityTickers() {
@@ -0,0 +1,25 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 28 Jul 2026 15:08:28 +0800
Subject: [PATCH] Anonymous Object: Fix wrong variable passing in
ThreadedRegionizer
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/io/papermc/paper/threadedregions/ThreadedRegionizer.java b/io/papermc/paper/threadedregions/ThreadedRegionizer.java
index a346b96500ae859e9469c80e2ff6b39c4d3d0b52..73e0aeb5a5e9bdd1f275dd64d1fffa32c389052d 100644
--- a/io/papermc/paper/threadedregions/ThreadedRegionizer.java
+++ b/io/papermc/paper/threadedregions/ThreadedRegionizer.java
@@ -755,8 +755,8 @@ public final class ThreadedRegionizer<R extends ThreadedRegionizer.ThreadedRegio
final int x1 = CoordinateUtils.getChunkX(k1);
final int x2 = CoordinateUtils.getChunkX(k2);
- final int z1 = CoordinateUtils.getChunkZ(x1);
- final int z2 = CoordinateUtils.getChunkZ(x2);
+ final int z1 = CoordinateUtils.getChunkZ(k1); // Anonymous - Fix wrong variable passing in ThreadedRegionizer
+ final int z2 = CoordinateUtils.getChunkZ(k2); // Anonymous - Fix wrong variable passing in ThreadedRegionizer
final int zCompare = Integer.compare(z1, z2);
if (zCompare != 0) {
@@ -0,0 +1,33 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 28 Jul 2026 15:08:42 +0800
Subject: [PATCH] Anonymous Object: Fix wrong ticket update determination in
RegionizedTaskQueue
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
index b264dbd13a392cde3f24ff75c0034985fda68ccc..fe0a6bd90cba4869a0ee11723832f2dee5039f62 100644
--- a/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
+++ b/io/papermc/paper/threadedregions/RegionizedTaskQueue.java
@@ -289,14 +289,17 @@ public final class RegionizedTaskQueue {
boolean executeTickTasks = allowedTickTasks > 0;
boolean executeChunkTasks = allowedChunkTasks > 0;
boolean executeGlobalTasks = true;
+ boolean processedChunkTask = false; // Anonymous - Fix wrong ticket update determination in RegionizedTaskQueue
do {
executeTickTasks = executeTickTasks && allowedTickTasks-- > 0 && tickTaskQueue.executeTask();
executeChunkTasks = executeChunkTasks && allowedChunkTasks-- > 0 && chunkTaskQueue.executeTask();
executeGlobalTasks = executeGlobalTasks && this.worldRegionTaskData.executeGlobalChunkTask();
+
+ processedChunkTask |= (executeChunkTasks | executeGlobalTasks); // Anonymous - Fix wrong ticket update determination in RegionizedTaskQueue
} while (executeTickTasks | executeChunkTasks | executeGlobalTasks);
- if (allowedChunkTasks > 0) {
+ if (processedChunkTask) { // Anonymous - Fix wrong ticket update determination in RegionizedTaskQueue
// if we executed chunk tasks, we should try to process ticket updates for full status changes
this.worldRegionTaskData.world.moonrise$getChunkTaskScheduler().chunkHolderManager.processTicketUpdates();
}
@@ -0,0 +1,23 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 28 Jul 2026 15:09:06 +0800
Subject: [PATCH] Anonymous Object: Lithium optimized collections for
WeightedList
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/util/random/WeightedList.java b/net/minecraft/util/random/WeightedList.java
index a8481259e42aa116e29bccd1e30fdfd91f51a8cc..49a558d6021db2d57eb2596206ea459fd33485e0 100644
--- a/net/minecraft/util/random/WeightedList.java
+++ b/net/minecraft/util/random/WeightedList.java
@@ -23,7 +23,7 @@ public class WeightedList<E> { // Paper - non-final
private final WeightedList.@Nullable Selector<E> selector;
protected WeightedList(final List<? extends Weighted<E>> items) { // Paper - protected
- this.items = List.copyOf(items);
+ this.items = items.size() > 4 ? new net.caffeinemc.mods.lithium.common.util.collections.HashedReferenceList(items) : new it.unimi.dsi.fastutil.objects.ReferenceArrayList<>(items); // Anonymous - Lithium optimized collections for WeightedList
this.totalWeight = WeightedRandom.getTotalWeight(items, Weighted::weight);
if (this.totalWeight == 0) {
this.selector = null;
@@ -0,0 +1,282 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 28 Jul 2026 15:09:19 +0800
Subject: [PATCH] Anonymous Object: Lithium optimized non poi block searching
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
index c6e9b155c2341c13d569f28f54f0c1d2d7313676..927635518c51375315390877d582b32fc38748df 100644
--- a/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
+++ b/net/minecraft/world/entity/ai/goal/MoveToBlockGoal.java
@@ -5,7 +5,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.level.LevelReader;
-public abstract class MoveToBlockGoal extends Goal {
+public abstract class MoveToBlockGoal extends Goal implements net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.LithiumMoveToBlockGoal { // Anonymous - Lithium Optimizes move to block goal
private static final int GIVE_UP_TICKS = 1200;
private static final int STAY_TICKS = 1200;
private static final int INTERVAL_TICKS = 200;
@@ -133,4 +133,167 @@ public abstract class MoveToBlockGoal extends Goal {
}
protected abstract boolean isValidTarget(LevelReader level, BlockPos pos);
+ // Anonymous start - Lithium Optimizes move to block goal
+ /**
+ * Finds the nearest block matching the predicates.
+ * <p>
+ * Side effect: The matching block position is stored in the blockPos field.
+ *
+ * @return Whether a matching block was found.
+ */
+ @Override
+ public boolean lithium$findNearestBlock(java.util.function.Predicate<net.minecraft.world.level.block.state.BlockState> requiredBlock, java.util.function.BiPredicate<net.minecraft.world.level.chunk.ChunkAccess,
+ BlockPos.MutableBlockPos> lithium$isValidTarget, final boolean shouldChunkLoad) {
+ //Center of the search starts 1 block below the mob's block position
+ BlockPos center = this.mob.blockPosition().offset(0,-1,0);
+
+ //Range is +-(searchRange - 1), +-verticalSearchRange, +-(searchRange - 1)
+ //Cache ChunkAccesses - getting them is surprisingly expensive - and track whether subchunks have the block
+ final LevelReader levelReader = this.mob.level();
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker checker = new net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker(center,
+ this.searchRange-1, this.verticalSearchRange,
+ levelReader, requiredBlock, shouldChunkLoad);
+ it.unimi.dsi.fastutil.longs.LongArrayList sortedChunksMaybeWithBlock = new it.unimi.dsi.fastutil.longs.LongArrayList(checker.getChunkSize());
+ checker.initializeChunks(sortedChunksMaybeWithBlock::addLast);
+
+ if (checker.shouldStop()) {
+ return false; //No chunks with the target block - return early
+ }
+
+ final int minY = net.caffeinemc.mods.lithium.common.util.Pos.BlockCoord.getMinY(levelReader);
+ final int maxY = net.caffeinemc.mods.lithium.common.util.Pos.BlockCoord.getMaxYInclusive(levelReader);
+
+ // Prefer chunk aware search because it also cuts iterations inside "empty" chunk sections
+ if(!checker.hasUnloadedPossibleChunks()){
+ return this.lithium$chunkAwareSearch(center, lithium$isValidTarget, checker, sortedChunksMaybeWithBlock, minY, maxY);
+ }
+
+ // Use vanilla search because unordered search may observably alter chunk-loading behavior
+ return this.lithium$vanillaOrderSearch(center, lithium$isValidTarget, checker, minY, maxY);
+ }
+
+ private boolean lithium$vanillaOrderSearch(BlockPos center,
+ java.util.function.BiPredicate<net.minecraft.world.level.chunk.ChunkAccess, BlockPos.MutableBlockPos> lithium$isValidTarget,
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker checker, final int minY, final int maxY) {
+ BlockPos.MutableBlockPos currentPos = new BlockPos.MutableBlockPos();
+ final int centerY = center.getY();
+
+ for (int layer = this.verticalSearchStart; layer <= this.verticalSearchRange; layer = layer > 0 ? -layer : 1 - layer) {
+ final int y = centerY + layer;
+
+ // Layer outside of build limit - skip
+ // Note: this is likely to be hit because farms where this lags tend to be built at world floor
+ if (y < minY || y > maxY) {
+ continue;
+ }
+
+ for (int ring = 0; ring < this.searchRange; ring++) {
+ for (int dX = 0; dX <= ring; dX = dX > 0 ? -dX : 1 - dX) {
+ for (int dZ = dX < ring && dX > -ring ? ring : 0; dZ <= ring; dZ = dZ > 0 ? -dZ : 1 - dZ) {
+ currentPos.setWithOffset(center, dX, layer, dZ);
+ if (this.mob.isWithinHome(currentPos) && checker.checkPosition(currentPos)) {
+ // ChunkAccess is always loaded at this point
+ net.minecraft.world.level.chunk.ChunkAccess chunkAccess = checker.getCachedChunkAccess(currentPos);
+ if (lithium$isValidTarget.test(chunkAccess, currentPos)){
+ this.blockPos = currentPos;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private boolean lithium$chunkAwareSearch(BlockPos center,
+ java.util.function.BiPredicate<net.minecraft.world.level.chunk.ChunkAccess, BlockPos.MutableBlockPos> lithium$isValidTarget,
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CheckAndCacheBlockChecker checker, it.unimi.dsi.fastutil.longs.LongArrayList sortedChunksMaybeWithBlock,
+ final int minY, final int maxY) {
+ // Sort chunks by lowest sort order - has the earliest searched position
+ // Note: In this search order, the closest point normally is also the closest point in the search
+ sortedChunksMaybeWithBlock.sort((chunkLong0, chunkLong1) ->
+ net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getMinimumSortOrderOfChunk(center, chunkLong0)
+ - net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getMinimumSortOrderOfChunk(center, chunkLong1)
+ );
+
+ java.util.function.Predicate<net.minecraft.world.level.block.state.BlockState> requiredBlock = checker.blockStatePredicate;
+ final int minSectionY = checker.minSectionY;
+
+ BlockPos.MutableBlockPos foundPos = new BlockPos.MutableBlockPos();
+ BlockPos.MutableBlockPos currentPos = new BlockPos.MutableBlockPos();
+
+ // Same layer order as vanilla - saves iterations if targets are found in the first layer
+ for (int layer = this.verticalSearchStart; layer <= this.verticalSearchRange; layer = layer > 0 ? -layer : 1 - layer) {
+ final int y = center.getY() + layer;
+
+ // Layer outside of build limit - skip
+ // Note: this is likely to be hit because farms where this lags tend to be built at world floor
+ if (y < minY || y > maxY) {
+ continue;
+ }
+
+ final int chunkY = net.minecraft.core.SectionPos.blockToSectionCoord(y);
+ final int ySectionIndex = chunkY - minSectionY;
+
+ int closestFound = Integer.MAX_VALUE;
+ int ringMax = this.searchRange - 1;
+
+ // Iterate through slices of chunks that may have the target blockState
+ for (long chunkPos: sortedChunksMaybeWithBlock) {
+ final int chunkX = net.minecraft.world.level.ChunkPos.getX(chunkPos);
+ final int chunkZ = net.minecraft.world.level.ChunkPos.getZ(chunkPos);
+
+ // Break since no subsequent chunks can be closer
+ if (closestFound < net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getMinimumSortOrderOfChunk(center, chunkX, chunkZ)) {
+ break;
+ }
+
+ // Skip if the current subchunk does not have the block
+ if (!checker.checkCachedSection(chunkX, chunkY, chunkZ)) {
+ continue;
+ }
+
+ net.minecraft.world.level.chunk.ChunkAccess chunkAccess = checker.getCachedChunkAccess(chunkPos);
+ // If ChunkSection may have close enough targets, iterate layer in Paletted Container (x then z) order
+ final int chunkBlockX = net.minecraft.core.SectionPos.sectionToBlockCoord(chunkX);
+ int xMin = Math.max(center.getX() - ringMax, chunkBlockX);
+ int xMax = Math.min(center.getX() + ringMax, chunkBlockX + 15);
+ final int chunkBlockZ = net.minecraft.core.SectionPos.sectionToBlockCoord(chunkZ);
+ int zMin = Math.max(center.getZ() - ringMax, chunkBlockZ);
+ int zMax = Math.min(center.getZ() + ringMax, chunkBlockZ + 15);
+ net.minecraft.world.level.chunk.LevelChunkSection levelChunkSection = chunkAccess.getSections()[ySectionIndex];
+ for (int z = zMin; z <= zMax; z++) {
+ for (int x = xMin; x <= xMax; x++) {
+ int dX = x - center.getX();
+ int dZ = z - center.getZ();
+ int ring = net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getRing(dX, dZ);
+ int currentDistance = net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.NonPOISearchDistances.MoveToBlockGoalDistances.getVanillaSortOrderInt(ring, dX, dZ);
+ if (currentDistance < closestFound
+ && this.mob.isWithinHome(currentPos.set(x, y, z))
+ && requiredBlock.test(levelChunkSection.getBlockState(x & 15, y & 15, z & 15))
+ && lithium$isValidTarget.test(chunkAccess, currentPos)) {
+ // Constrain search size when we find a valid target
+ ringMax = ring;
+ xMin = Math.max(center.getX() - ringMax, chunkBlockX);
+ xMax = Math.min(center.getX() + ringMax, chunkBlockX + 15);
+ zMax = Math.min(center.getZ() + ringMax, chunkBlockZ + 15);
+ foundPos.set(x, y, z);
+ closestFound = currentDistance;
+ }
+ }
+ }
+ }
+
+ if (closestFound < Integer.MAX_VALUE) {
+ // Vanilla uses the mutable pos, no need to create immutable copy
+ this.blockPos = foundPos;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ // Anonymous end - Lithium Optimizes move to block goal
}
diff --git a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
index ff0f99d4b560a1c0721885b0eba5bd5ab2087bd7..99c076ee2fe0d8294398c5ef1f24a95da5eee89c 100644
--- a/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
+++ b/net/minecraft/world/entity/ai/goal/RemoveBlockGoal.java
@@ -25,6 +25,19 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
private final Mob removerMob;
private int ticksSinceReachedGoal;
private static final int WAIT_AFTER_BLOCK_FOUND = 20;
+ // Anonymous start - Lithium Optimize remove block goal
+ private static final java.util.function.BiPredicate<ChunkAccess, BlockPos.MutableBlockPos> IS_VALID_TARGET_ABOVE_BIPREDICATE =
+ RemoveBlockGoal::lithium$isValidTargetAbove;
+ //Split check condition in order to use maybeHas
+ private boolean lithium$isValidTargetBlock(net.minecraft.world.level.block.state.BlockState blockState){
+ return blockState.is(this.blockToRemove);
+ }
+
+ private static boolean lithium$isValidTargetAbove(ChunkAccess chunkAccess, BlockPos.MutableBlockPos mutable) {
+ return chunkAccess.getBlockState(mutable.move(0, 1, 0)).isAir()
+ && chunkAccess.getBlockState(mutable.move(0, 1, 0)).isAir();
+ }
+ // Anonymous end - Lithium Optimize remove block goal
public RemoveBlockGoal(final Block blockToRemove, final PathfinderMob mob, final double speedModifier, final int verticalSearchRange) {
super(mob, speedModifier, 24, verticalSearchRange);
@@ -39,7 +52,7 @@ public class RemoveBlockGoal extends MoveToBlockGoal {
} else if (this.nextStartTick > 0) {
this.nextStartTick--;
return false;
- } else if (this.findNearestBlock()) {
+ } else if (((net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.LithiumMoveToBlockGoal) this).lithium$findNearestBlock(this::lithium$isValidTargetBlock, IS_VALID_TARGET_ABOVE_BIPREDICATE, false)) { // Anonymous - Lithium Optimize remove block goal
this.nextStartTick = reducedTickDelay(20);
return true;
} else {
diff --git a/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java b/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java
index 7022679c84e184999b416e06d1af2cc2500cb12b..78743515ff2afd1ea1f06432f33f41a03fc7988b 100644
--- a/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java
+++ b/net/minecraft/world/entity/ai/sensing/HoglinSpecificSensor.java
@@ -16,6 +16,14 @@ import net.minecraft.world.entity.monster.hoglin.Hoglin;
import net.minecraft.world.entity.monster.piglin.Piglin;
public class HoglinSpecificSensor extends Sensor<Hoglin> {
+ // Anonymous start - Lithium Optimizes Hoglin repellent search.
+ private static final java.util.function.Predicate<net.minecraft.world.level.block.state.BlockState> IS_VALID_REPELLENT_PREDICATE =
+ HoglinSpecificSensor::lithium$isValidRepellent;
+
+ private static boolean lithium$isValidRepellent(net.minecraft.world.level.block.state.BlockState blockState) {
+ return blockState.is(BlockTags.HOGLIN_REPELLENTS);
+ }
+ // Anonymous end - Lithium Optimizes Hoglin repellent search.
@Override
public Set<MemoryModuleType<?>> requires() {
return ImmutableSet.of(
@@ -30,8 +38,8 @@ public class HoglinSpecificSensor extends Sensor<Hoglin> {
@Override
protected void doTick(final ServerLevel level, final Hoglin body) {
- Brain<?> brain = body.getBrain();
- brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, this.findNearestRepellent(level, body));
+ Brain<?> brain = body.getBrain();;
+ brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CommonBlockSearchesCheckAndCache.blockPosFindClosestMatch(level, body, 8, 4, IS_VALID_REPELLENT_PREDICATE, true)); // Anonymous - Lithium Optimizes Hoglin repellent search.
Optional<Piglin> adultPiglin = Optional.empty();
int adultPiglinCount = 0;
List<Hoglin> adultHoglins = Lists.newArrayList();
diff --git a/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java b/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java
index 060a53da799a3036a343cc6f1d73e3e5ca4b7af9..8594f559a5c8f5957348f7178464d5e9c5abc5ff 100644
--- a/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java
+++ b/net/minecraft/world/entity/ai/sensing/PiglinSpecificSensor.java
@@ -26,6 +26,15 @@ import net.minecraft.world.level.block.CampfireBlock;
import net.minecraft.world.level.block.state.BlockState;
public class PiglinSpecificSensor extends Sensor<LivingEntity> {
+ // Anonymous start - Lithium Optimizes Piglin repellent search.
+ private static final java.util.function.Predicate<BlockState> IS_VALID_REPELLENT_PREDICATE =
+ PiglinSpecificSensor::lithium$isValidRepellent;
+ private static boolean lithium$isValidRepellent(BlockState blockState){
+ final boolean isPiglinRepellent = blockState.is(BlockTags.PIGLIN_REPELLENTS);
+ return isPiglinRepellent && blockState.is(Blocks.SOUL_CAMPFIRE) ?
+ CampfireBlock.isLitCampfire(blockState) : isPiglinRepellent;
+ }
+ // Anonymous end - Lithium Optimizes Piglin repellent search.
@Override
public Set<MemoryModuleType<?>> requires() {
return ImmutableSet.of(
@@ -47,7 +56,7 @@ public class PiglinSpecificSensor extends Sensor<LivingEntity> {
@Override
protected void doTick(final ServerLevel level, final LivingEntity body) {
Brain<?> brain = body.getBrain();
- brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, findNearestRepellent(level, body));
+ brain.setMemory(MemoryModuleType.NEAREST_REPELLENT, net.caffeinemc.mods.lithium.common.ai.non_poi_block_search.CommonBlockSearchesCheckAndCache.blockPosFindClosestMatch(level, body, 8, 4, IS_VALID_REPELLENT_PREDICATE, true)); // Anonymous - Lithium Optimizes Piglin repellent search.
Optional<Mob> nemesis = Optional.empty();
Optional<Hoglin> huntableHoglin = Optional.empty();
Optional<Hoglin> babyHoglin = Optional.empty();
@@ -4,6 +4,7 @@ import ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO;
import com.github.luben.zstd.ZstdInputStream;
import com.github.luben.zstd.ZstdOutputStream;
import com.mojang.logging.LogUtils;
import io.anonymous.anonymous.data.RegionFile;
import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;
@@ -26,7 +27,7 @@ import java.util.concurrent.locks.ReentrantLock;
// LinearRegionFile_implementation_version_0_5byXymb
// Just gonna use this string to inform other forks about updates ;-)
public class LinearRegionFile implements IRegionFile {
public class LinearRegionFile implements RegionFile {
private static final long SUPERBLOCK = 0xc3ff13183cca9d9aL;
private static final byte VERSION = 3;
private static final int HEADER_SIZE = 27;
@@ -489,15 +490,15 @@ public class LinearRegionFile implements IRegionFile {
public DataOutputStream getChunkDataOutputStream(ChunkPos pos) {
openRegionFile();
openBucket(pos.x(), pos.z());
return new DataOutputStream(new BufferedOutputStream(new LinearRegionFile.ChunkBuffer(pos)));
return new DataOutputStream(new BufferedOutputStream(new ChunkBuffer(pos)));
}
@Override
public MoonriseRegionFileIO.RegionDataController.WriteData moonrise$startWrite(CompoundTag data, ChunkPos pos) throws IOException {
final DataOutputStream out = this.getChunkDataOutputStream(pos);
return new ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData(
data, ca.spottedleaf.moonrise.patches.chunk_system.io.MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.WRITE,
return new MoonriseRegionFileIO.RegionDataController.WriteData(
data, MoonriseRegionFileIO.RegionDataController.WriteData.WriteResult.WRITE,
out, regionFile -> out.close()
);
}
@@ -21,5 +21,4 @@ public final class MathUtilities {
int i = (int) d;
return d > (double) i ? i + 1 : i;
}
}
@@ -6,7 +6,6 @@ import me.earthme.luminol.config.ConfigsInstance;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
@@ -16,46 +15,15 @@ public class GlobalEntitiesCounter implements IConfigModule {
@ConfigInfo(name = "version")
public static GlobalEntitiesCounterType type = GlobalEntitiesCounterType.DISABLED;
@DoNotLoad
private static boolean enabled;
@DoNotLoad
private static boolean async;
@DoNotLoad
private static boolean defaultModule;
public static boolean isEnabled() {
return enabled;
return type.isEnabled();
}
public static boolean isAsync() {
return async;
return type.isAsync();
}
public static boolean isDefaultModule() {
return defaultModule;
}
@Override
public void beforeFinalLoad() {
ConfigsInstance configsInstance = ConfigManager.getConfigs("lophine");
try {
Boolean enabled0 = configsInstance.getConfigOrigin("experiment.global_entities_counter.enabled");
Boolean async0 = configsInstance.getConfigOrigin("experiment.global_entities_counter.async");
if (enabled0 != null) {
if (enabled0) {
if (async0 != null && async0) {
type = GlobalEntitiesCounterType.DEFAULT_ASYNC;
} else {
type = GlobalEntitiesCounterType.DEFAULT_SYNC;
}
}
}
configsInstance.removeConfig("experiment.global_entities_counter.enabled");
configsInstance.removeConfig("experiment.global_entities_counter.async");
} catch (Exception ignored) {
}
enabled = type != GlobalEntitiesCounterType.DISABLED;
async = type == GlobalEntitiesCounterType.DEFAULT_ASYNC;
defaultModule = type == GlobalEntitiesCounterType.DEFAULT_SYNC || type == GlobalEntitiesCounterType.DEFAULT_ASYNC;
return type.isDefaultModule();
}
}
@@ -1,8 +1,30 @@
package fun.bm.lophine.enums;
public enum GlobalEntitiesCounterType {
DISABLED,
DEFAULT_SYNC,
DEFAULT_ASYNC,
PRECISE
DISABLED(false, false, false),
DEFAULT_SYNC(true, false, true),
DEFAULT_ASYNC(true, true, true),
PRECISE(true, false, false);
private boolean enabled;
private boolean async;
private boolean defaultModule;
private GlobalEntitiesCounterType(boolean enabled, boolean async, boolean defaultModule) {
this.enabled = enabled;
this.async = async;
this.defaultModule = defaultModule;
}
public boolean isEnabled() {
return enabled;
}
public boolean isAsync() {
return async;
}
public boolean isDefaultModule() {
return defaultModule;
}
}
@@ -23,7 +23,6 @@ import io.sentry.Breadcrumb;
import io.sentry.Sentry;
import io.sentry.SentryEvent;
import io.sentry.SentryLevel;
import io.sentry.protocol.Message;
import io.sentry.protocol.User;
import me.earthme.luminol.config.modules.misc.SentryConfig;
import org.apache.logging.log4j.Level;
@@ -67,9 +66,6 @@ public class PufferfishSentryAppender extends AbstractAppender {
private void logException(LogEvent e) {
SentryEvent event = new SentryEvent(e.getThrown());
Message sentryMessage = new Message();
sentryMessage.setMessage(e.getMessage().getFormattedMessage());
event.setThrowable(e.getThrown());
event.setLevel(getLevel(e.getLevel()));
event.setLogger(e.getLoggerName());
@@ -26,10 +26,6 @@ public class SentryManager {
private static final Logger logger = LogManager.getLogger(SentryManager.class);
private SentryManager() {
}
private static boolean initialized = false;
public static synchronized void init(Level logLevel) {
@@ -1,10 +1,9 @@
package me.earthme.luminol.utils;
package io.anonymous.anonymous.data;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import me.earthme.luminol.data.BufferedLinearRegionFile;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
@@ -1,4 +1,5 @@
package abomination;
package io.anonymous.anonymous.data;
import ca.spottedleaf.moonrise.patches.chunk_system.storage.ChunkSystemRegionFile;
import net.minecraft.nbt.CompoundTag;
@@ -10,7 +11,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.file.Path;
public interface IRegionFile extends ChunkSystemRegionFile, AutoCloseable {
public interface RegionFile extends ChunkSystemRegionFile, AutoCloseable {
Path getPath();
DataInputStream getChunkDataInputStream(ChunkPos pos) throws IOException;
@@ -39,5 +40,5 @@ public interface IRegionFile extends ChunkSystemRegionFile, AutoCloseable {
default int getRecalculateCount() {
return 0;
} // Luminol - Configurable region file format
} // Anonymous - Configurable region file format
}
@@ -1,9 +1,9 @@
package me.earthme.luminol.enums;
package io.anonymous.anonymous.enums;
import abomination.LinearRegionFile;
import me.earthme.luminol.config.modules.function.RegionFormatConfig;
import me.earthme.luminol.data.BufferedLinearRegionFile;
import me.earthme.luminol.utils.IRegionCreateFunction;
import io.anonymous.anonymous.data.BufferedLinearRegionFile;
import io.anonymous.anonymous.utils.RegionFileFactory;
import net.minecraft.world.level.chunk.storage.RegionFile;
public enum EnumRegionFormat {
@@ -12,14 +12,14 @@ public enum EnumRegionFormat {
B_LINEAR("b_linear", (info) -> new BufferedLinearRegionFile(info.filePath(), RegionFormatConfig.linearCompressionLevel, RegionFormatConfig.blinearFlusher));
private final String argument;
private final IRegionCreateFunction creator;
private final RegionFileFactory creator;
EnumRegionFormat(String argument, IRegionCreateFunction creator) {
EnumRegionFormat(String argument, RegionFileFactory creator) {
this.argument = argument;
this.creator = creator;
}
public IRegionCreateFunction getCreator() {
public RegionFileFactory getCreator() {
return this.creator;
}
@@ -1,4 +1,4 @@
package me.earthme.luminol.utils;
package io.anonymous.anonymous.utils;
import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
@@ -0,0 +1,10 @@
package io.anonymous.anonymous.utils;
import io.anonymous.anonymous.data.RegionFile;
import java.io.IOException;
@FunctionalInterface
public interface RegionFileFactory {
RegionFile newFile(RegionCreatorInfo info) throws IOException;
}
@@ -9,8 +9,8 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
import me.earthme.luminol.enums.EnumRegionFormat;
import me.earthme.luminol.utils.BufferedLinearRegionFileFlusher;
import io.anonymous.anonymous.enums.EnumRegionFormat;
import io.anonymous.anonymous.data.BufferedLinearRegionFileFlusher;
import net.minecraft.server.MinecraftServer;
import org.jetbrains.annotations.Nullable;
@@ -1,10 +0,0 @@
package me.earthme.luminol.utils;
import abomination.IRegionFile;
import java.io.IOException;
@FunctionalInterface
public interface IRegionCreateFunction {
IRegionFile create(RegionCreatorInfo info) throws IOException;
}
@@ -0,0 +1,159 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.mods.lithium.common.ai.non_poi_block_search;
import net.caffeinemc.mods.lithium.common.util.collections.FixedChunkAccessSectionBitBuffer;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* This is intended to be used to optimize Non-POI block searches by pre-checking the ChunkSections, getting the
* ChunkAccesses which then allows for returning early or only calling getBlockState in possible ChunkSections.
* <p>
* Note: Please correctly specify shouldChunkLoad based on whether the getBlockState in vanilla can chunk load or not.
* The default in game is that it can. Setting it to true will mean that the search will assume that unloaded chunks
* may have the target and will chunk load then search them if and when it reaches it.
*
* @author jcw780
*/
public class CheckAndCacheBlockChecker {
private final FixedChunkAccessSectionBitBuffer chunkSections2MaybeContainsMatchingBlock;
private final LevelReader levelReader;
public final boolean shouldChunkLoad;
public final Predicate<BlockState> blockStatePredicate;
private int unloadedPossibleChunkSections = 0;
public final int minSectionY;
public CheckAndCacheBlockChecker(BlockPos origin, int horizontalRangeInclusive, int verticalRangeInclusive, LevelReader levelReader,
Predicate<BlockState> blockStatePredicate, boolean shouldChunkLoad) {
this.chunkSections2MaybeContainsMatchingBlock = new FixedChunkAccessSectionBitBuffer(origin, horizontalRangeInclusive, verticalRangeInclusive);
this.levelReader = levelReader;
this.shouldChunkLoad = shouldChunkLoad;
this.blockStatePredicate = blockStatePredicate;
this.minSectionY = levelReader.getMinSectionY();
}
public void initializeChunks() {
this.initializeChunks(null);
}
public void initializeChunks(Consumer<Long> chunkCollector) {
final boolean nullChunkCollector = chunkCollector == null;
for (long chunkPos : this.chunkSections2MaybeContainsMatchingBlock.getChunkPosInRange()) {
int x = ChunkPos.getX(chunkPos);
int z = ChunkPos.getZ(chunkPos);
boolean chunkMaybeHas = false;
//Never load chunks in the first pass to avoid observably altering chunk loading behavior
//Otherwise full region will be loaded vs partial region if the search finds the block early.
ChunkAccess chunkAccess = levelReader.getChunk(x, z, ChunkStatus.FULL, false);
if (chunkAccess != null) {
this.chunkSections2MaybeContainsMatchingBlock.setChunkAccess(chunkPos, chunkAccess);
for (int y : this.chunkSections2MaybeContainsMatchingBlock.getSectionYInRange()) {
chunkMaybeHas = this.checkChunkSection(chunkAccess, x, y, z) || chunkMaybeHas;
}
} else if (this.shouldChunkLoad) {
/* If the search may chunk load then it is possible that target blocks may be revealed when the search
* reaches it. Since we cannot load the chunks and check now, we cannot definitively exclude subchunks
* inside the chunk. This means that we must flag subchunks that are within build limit - otherwise air
* anyway - for the search.
*/
for (int y : this.chunkSections2MaybeContainsMatchingBlock.getSectionYInRange()) {
this.chunkSections2MaybeContainsMatchingBlock.setChunkSectionStatus(SectionPos.asLong(x, y, z),
!levelReader.isOutsideBuildHeight(SectionPos.sectionToBlockCoord(y)));
++this.unloadedPossibleChunkSections;
}
chunkMaybeHas = true;
}
if (!nullChunkCollector && chunkMaybeHas) {
chunkCollector.accept(chunkPos);
}
}
}
public int getChunkSize(){
return this.chunkSections2MaybeContainsMatchingBlock.numChunks;
}
public boolean hasUnloadedPossibleChunks(){
return this.unloadedPossibleChunkSections > 0;
}
private boolean checkChunkSection(ChunkAccess chunkAccess, int chunkX, int chunkY, int chunkZ) {
final int chunkSectionYIndex = chunkY - this.minSectionY;
LevelChunkSection[] chunkSections = chunkAccess.getSections();
if (chunkSectionYIndex >= 0
&& chunkSectionYIndex < chunkSections.length
&& chunkSections[chunkSectionYIndex].maybeHas(blockStatePredicate)) {
this.chunkSections2MaybeContainsMatchingBlock.setChunkSectionStatus(
SectionPos.asLong(chunkX, chunkY, chunkZ), true);
return true;
}
return false;
}
public boolean checkCachedSection(int chunkX, int chunkY, int chunkZ) {
return this.chunkSections2MaybeContainsMatchingBlock.getChunkSectionBit(chunkX, chunkY, chunkZ);
}
public ChunkAccess getCachedChunkAccess(long chunkPos) {
return this.chunkSections2MaybeContainsMatchingBlock.getChunkAccess(chunkPos);
}
public ChunkAccess getCachedChunkAccess(BlockPos blockPos) {
return this.chunkSections2MaybeContainsMatchingBlock.getChunkAccess(blockPos);
}
public boolean shouldStop(){
return this.chunkSections2MaybeContainsMatchingBlock.hasNoTrueChunkSections();
}
public boolean checkPosition(BlockPos blockPos) {
if(!this.chunkSections2MaybeContainsMatchingBlock.getChunkSectionBit(blockPos)) return false;
ChunkAccess chunkAccess = this.chunkSections2MaybeContainsMatchingBlock.getChunkAccess(blockPos);
if(chunkAccess == null) {
if (!this.shouldChunkLoad) {
return false;
}
final int chunkX = SectionPos.blockToSectionCoord(blockPos.getX());
final int chunkY = SectionPos.blockToSectionCoord(blockPos.getY());
final int chunkZ = SectionPos.blockToSectionCoord(blockPos.getZ());
chunkAccess = levelReader.getChunk(chunkX, chunkZ, ChunkStatus.FULL, true);
//this chunkAccess cannot be null and reach here because it should throw earlier
assert chunkAccess != null;
this.chunkSections2MaybeContainsMatchingBlock.setChunkAccess(blockPos, chunkAccess);
if (!checkChunkSection(chunkAccess, chunkX, chunkY, chunkZ)) {
--this.unloadedPossibleChunkSections;
return false;
}
}
return blockStatePredicate.test(chunkAccess.getBlockState(blockPos));
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.mods.lithium.common.ai.non_poi_block_search;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Optional;
import java.util.function.Predicate;
/**
* Uses CheckAndCacheBlockChecker to improve common block searches
*/
public class CommonBlockSearchesCheckAndCache {
/**
* Optimizes BlockPos::findClosestMatch
* [Vanilla Copy] search order and chunk-loading - even though the latter is unlikely to be observable in vanilla.
*/
public static Optional<BlockPos> blockPosFindClosestMatch(LevelReader levelReader, LivingEntity livingEntity,
int horizontalRange, int verticalRange,
Predicate<BlockState> blockStatePredicate,
boolean shouldChunkLoad){
BlockPos mobPos = livingEntity.blockPosition();
CheckAndCacheBlockChecker checker = new CheckAndCacheBlockChecker(
mobPos, horizontalRange, verticalRange, levelReader, blockStatePredicate, shouldChunkLoad);
checker.initializeChunks();
if(checker.shouldStop()) {
return Optional.empty();
}
return BlockPos.findClosestMatch(mobPos, horizontalRange, verticalRange, checker::checkPosition);
}
}
@@ -0,0 +1,30 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.mods.lithium.common.ai.non_poi_block_search;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
public interface LithiumMoveToBlockGoal {
boolean lithium$findNearestBlock(Predicate<BlockState> requiredBlock,
BiPredicate<ChunkAccess, BlockPos.MutableBlockPos> lithium$isValidTarget,
final boolean shouldChunkLoad);
}
@@ -0,0 +1,68 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.mods.lithium.common.ai.non_poi_block_search;
import net.caffeinemc.mods.lithium.common.util.Distances;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.ChunkPos;
public class NonPOISearchDistances {
public static class MoveToBlockGoalDistances {
public static int getMinimumSortOrderOfChunk(BlockPos center, final long chunkPos) {
return getMinimumSortOrderOfChunk(center, ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos));
}
public static int getMinimumSortOrderOfChunk(BlockPos center, final int chunkX, final int chunkZ) {
final int dX = Distances.getClosestBlockCoordInSection(center.getX(), chunkX) - center.getX();
final int dZ = Distances.getClosestBlockCoordInSection(center.getZ(), chunkZ) - center.getZ();
//This will always get the closest one due to the nature of the search
return getVanillaSortOrderInt(getRing(dX, dZ), dX, dZ);
}
public static int getRing(final int dX, final int dZ){
return Math.max(Math.abs(dX), Math.abs(dZ));
}
/**
* Sort order function for 1 layer of MoveToBlockGoal findNearestBlock
* This is equivalent to:
* int withinRingX = Math.abs(dX) * 2 - (dX > 0 ? 1 : 0);
* int withinRingZ = Math.abs(dZ) * 2 - (dZ > 0 ? 1 : 0);
* return ring << 16 | withinRingX << 8 | withinRingZ;
* <p>
* This works because the search prioritizes in order of:
* 1. The distance of y from the center - Not used
* 2. Whether y is - or + (+ is closer) - Not used
* 3. The square ring that the block is in (outer is further)
* 4. The distance of x from the center
* 5. Whether x is - or + (+ is closer)
* 6. The distance of z from the center
* 7. Whether z is - or + (+ is closer)
* <p>
* Note: The bit-packing only works for horizontal search ranges of <=128.
* You can convert to longs if you somehow exceed that, but also seriously consider POIs instead.
*
* @param ring Which square ring the block is at relative to the center
* @param dX Relative x position of the block to the center
* @param dZ Relative z position of the block to the center
*/
public static int getVanillaSortOrderInt(final int ring, final int dX, final int dZ) {
return (ring << 16 | Math.abs(dX) << 9 | Math.abs(dZ) << 1) - ((dX > 0 ? 1 : 0) << 8 | (dZ > 0 ? 1 : 0));
}
}
}
@@ -0,0 +1,83 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.mods.lithium.common.util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
public class Distances {
public static long getMinChunkToBlockDistanceL2Sq(BlockPos origin, int chunkX, int chunkZ) {
int chunkMinX = SectionPos.sectionToBlockCoord(chunkX);
int chunkMinZ = SectionPos.sectionToBlockCoord(chunkZ);
int xDistance = origin.getX() - chunkMinX;
if (xDistance > 0) {
xDistance = Math.max(0, xDistance - 15);
}
int zDistance = origin.getZ() - chunkMinZ;
if (zDistance > 0) {
zDistance = Math.max(0, zDistance - 15);
}
return (long) xDistance * (long) xDistance + (long) zDistance * (long) zDistance;
}
public static BlockPos getClosestPosInChunk(BlockPos origin, int chunkX, int chunkZ) {
int closestX = getClosestBlockCoordInSection(origin.getX(), chunkX);
int closestZ = getClosestBlockCoordInSection(origin.getZ(), chunkZ);
return new BlockPos(closestX, origin.getY(), closestZ);
}
public static boolean isWithinCubeRadius(BlockPos origin, int radius, BlockPos pos) {
return Math.abs(pos.getX() - origin.getX()) <= radius &&
Math.abs(pos.getZ() - origin.getZ()) <= radius;
}
public static boolean isWithinSphereRadius(BlockPos origin, long radiusSq, BlockPos pos) {
return distanceSq(origin, pos) <= radiusSq;
}
public static int getClosestBlockCoordInSection(int blockCoord, int sectionCoord) {
final int minBlockInSection = SectionPos.sectionToBlockCoord(sectionCoord);
return Math.min(Math.max(blockCoord, minBlockInSection), minBlockInSection + 15);
}
public static long getMinSectionDistanceSq(BlockPos origin, int chunkX, int chunkY, int chunkZ) {
int originX = origin.getX(), originY = origin.getY(), originZ = origin.getZ();
long distX = getClosestBlockCoordInSection(originX, chunkX) - originX;
long distY = getClosestBlockCoordInSection(originY, chunkY) - originY;
long distZ = getClosestBlockCoordInSection(originZ, chunkZ) - originZ;
return distX * distX + distY * distY + distZ * distZ;
}
public static long distanceSq(BlockPos a, BlockPos b) {
long dx = a.getX() - b.getX();
long dy = a.getY() - b.getY();
long dz = a.getZ() - b.getZ();
return dx * dx + dy * dy + dz * dz;
}
public static int distanceSqInt(BlockPos a, BlockPos b) {
int dx = a.getX() - b.getX();
int dy = a.getY() - b.getY();
int dz = a.getZ() - b.getZ();
// Check overflows to avoid silent incorrect results
return Math.addExact(Math.addExact(Math.multiplyExact(dx, dx), Math.multiplyExact(dy, dy)), Math.multiplyExact(dz, dz));
}
}
@@ -0,0 +1,109 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.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.getMinY();
}
public static int getMaxYInclusive(LevelHeightAccessor view) {
return view.getMaxY();
}
public static int getMaxYExclusive(LevelHeightAccessor view) {
return view.getMaxY() + 1;
}
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.getMinSectionY();
}
public static int getMaxYSectionInclusive(LevelHeightAccessor view) {
return view.getMaxSectionY();
}
public static int getMaxYSectionExclusive(LevelHeightAccessor view) {
return view.getMaxSectionY() + 1;
}
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));
}
}
}
@@ -0,0 +1,189 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.mods.lithium.common.util.collections;
import it.unimi.dsi.fastutil.ints.IntIterable;
import it.unimi.dsi.fastutil.ints.IntIterator;
import it.unimi.dsi.fastutil.longs.LongIterable;
import it.unimi.dsi.fastutil.longs.LongIterator;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
public class FixedChunkAccessSectionBitBuffer {
public final int xMin, yMin, zMin;
public final int xLength, yLength, zLength, numChunks, numSections;
public final BitSet chunkSectionBits;
public final ArrayList<ChunkAccess> chunkAccesses;
public FixedChunkAccessSectionBitBuffer(int x0, int x1, int y0, int y1, int z0, int z1) {
this.xMin = Math.min(x0, x1);
this.yMin = Math.min(y0, y1);
this.zMin = Math.min(z0, z1);
this.xLength = Math.max(x0, x1) - this.xMin + 1;
this.yLength = Math.max(y0, y1) - this.yMin + 1;
this.zLength = Math.max(z0, z1) - this.zMin + 1;
this.numChunks = xLength * zLength;
this.numSections = yLength * xLength * zLength;
this.chunkSectionBits = new BitSet(numSections);
this.chunkAccesses = new ArrayList<>(Collections.nCopies(xLength * zLength,null));
}
public FixedChunkAccessSectionBitBuffer(BlockPos center, int horizontalRangeInclusive, int verticalRangeInclusive) {
this(SectionPos.blockToSectionCoord(center.getX() - horizontalRangeInclusive),
SectionPos.blockToSectionCoord(center.getX() + horizontalRangeInclusive),
SectionPos.blockToSectionCoord(center.getY() - verticalRangeInclusive),
SectionPos.blockToSectionCoord(center.getY() + verticalRangeInclusive),
SectionPos.blockToSectionCoord(center.getZ() - horizontalRangeInclusive),
SectionPos.blockToSectionCoord(center.getZ() + horizontalRangeInclusive)
);
}
public int getSectionIndex(int x, int y, int z) {
int dx = x - this.xMin;
int dy = y - this.yMin;
int dz = z - this.zMin;
return (dx * this.zLength + dz) * this.yLength + dy;
}
public int getSectionIndex(long sectionPos) {
return this.getSectionIndex(
SectionPos.x(sectionPos),
SectionPos.y(sectionPos),
SectionPos.z(sectionPos)
);
}
public boolean getChunkSectionBit(BlockPos blockPos) {
return this.getChunkSectionBit(SectionPos.blockToSectionCoord(blockPos.getX()), SectionPos.blockToSectionCoord(blockPos.getY()), SectionPos.blockToSectionCoord(blockPos.getZ()));
}
public boolean getChunkSectionBit(int chunkX, int chunkY, int chunkZ) {
return this.chunkSectionBits.get(this.getSectionIndex(chunkX, chunkY, chunkZ));
}
public void setChunkSectionStatus(long sectionPos, boolean value) {
this.chunkSectionBits.set(this.getSectionIndex(sectionPos), value);
}
public int getChunkIndex(int x, int z) {
int dx = x - this.xMin;
int dz = z - this.zMin;
return dx * this.zLength + dz;
}
public int getChunkIndex(long chunkPos) {
return this.getChunkIndex(ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos));
}
public ChunkAccess getChunkAccess(long chunkPos){
return this.chunkAccesses.get(this.getChunkIndex(chunkPos));
}
public ChunkAccess getChunkAccess(BlockPos blockPos){
return this.getChunkAccess(ChunkPos.pack(blockPos));
}
public void setChunkAccess(long chunkPos, ChunkAccess chunkAccess) {
this.chunkAccesses.set(this.getChunkIndex(chunkPos), chunkAccess);
}
public void setChunkAccess(BlockPos blockPos, ChunkAccess chunkAccess) {
this.setChunkAccess(ChunkPos.pack(blockPos), chunkAccess);
}
public boolean hasNoTrueChunkSections(){
return this.chunkSectionBits.nextSetBit(0) == -1;
}
public LongIterable getChunkPosInRange() {
return new LongIterable() {
@Override
public @NotNull LongIterator iterator(){
return getChunkPosInRangeIterator();
}
};
}
public LongIterator getChunkPosInRangeIterator() {
final int xMin = this.xMin;
final int xMax = this.xMin + this.xLength - 1;
final int zMin = this.zMin;
final int zMax = this.zMin + this.zLength - 1;
return new LongIterator() {
int x = xMin;
int z = zMin;
@Override
public long nextLong () {
long result = ChunkPos.pack(x, z);
if (z < zMax) {
z++;
} else {
z = zMin;
x++;
}
return result;
}
@Override
public boolean hasNext(){
return x <= xMax;
}
};
}
public IntIterable getSectionYInRange() {
return new IntIterable() {
@Override
public @NotNull IntIterator iterator(){
return getSectionYInRangeIterator();
}
};
}
public IntIterator getSectionYInRangeIterator() {
final int yMin = this.yMin;
final int yLimit = yMin + this.yLength;
return new IntIterator() {
int y = yMin;
@Override
public int nextInt(){
return y++;
}
@Override
public boolean hasNext(){
return y < yLimit;
}
};
}
}
@@ -0,0 +1,293 @@
/*
* This file is part of Lithium
*
* Lithium is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Lithium is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Lithium. If not, see <https://www.gnu.org/licenses/>.
*/
package net.caffeinemc.mods.lithium.common.util.collections;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
import org.jetbrains.annotations.NotNull;
import java.util.*;
/**
* Wraps a {@link List} with a hash table which provides O(1) lookups for {@link Collection#contains(Object)}. The type
* contained by this list must use reference-equality semantics.
*/
@SuppressWarnings("SuspiciousMethodCalls")
public class HashedReferenceList<T> implements List<T> {
private final ReferenceArrayList<T> list;
private final Reference2IntOpenHashMap<T> counter;
public HashedReferenceList(Collection<T> list) {
this.list = new ReferenceArrayList<>();
this.list.addAll(list);
this.counter = new Reference2IntOpenHashMap<>();
this.counter.defaultReturnValue(0);
for (T obj : this.list) {
this.counter.addTo(obj, 1);
}
}
@Override
public int size() {
return this.list.size();
}
@Override
public boolean isEmpty() {
return this.list.isEmpty();
}
@Override
public boolean contains(Object o) {
return this.counter.containsKey(o);
}
@Override
public Iterator<T> iterator() {
return this.listIterator();
}
@Override
public Object[] toArray() {
return this.list.toArray();
}
@Override
public <T1> T1[] toArray(T1 @NotNull [] a) {
return this.list.toArray(a);
}
@Override
public boolean add(T t) {
this.trackReferenceAdded(t);
return this.list.add(t);
}
@Override
public boolean remove(Object o) {
this.trackReferenceRemoved(o);
return this.list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
for (Object obj : c) {
if (!this.counter.containsKey(obj)) {
return false;
}
}
return true;
}
@Override
public boolean addAll(Collection<? extends T> c) {
for (T obj : c) {
this.trackReferenceAdded(obj);
}
return this.list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends T> c) {
for (T obj : c) {
this.trackReferenceAdded(obj);
}
return this.list.addAll(index, c);
}
@Override
public boolean removeAll(@NotNull Collection<?> c) {
if (this.size() >= 2 && c.size() > 4 && c instanceof List) {
//HashReferenceList uses reference equality, so using ReferenceOpenHashSet is fine
c = new ReferenceOpenHashSet<>(c);
}
this.counter.keySet().removeAll(c);
return this.list.removeAll(c);
}
@Override
public boolean retainAll(@NotNull Collection<?> c) {
this.counter.keySet().retainAll(c);
return this.list.retainAll(c);
}
@Override
public void clear() {
this.counter.clear();
this.list.clear();
}
@Override
public T get(int index) {
return this.list.get(index);
}
@Override
public T set(int index, T element) {
T prev = this.list.set(index, element);
if (prev != element) {
if (prev != null) {
this.trackReferenceRemoved(prev);
}
this.trackReferenceAdded(element);
}
return prev;
}
@Override
public void add(int index, T element) {
this.trackReferenceAdded(element);
this.list.add(index, element);
}
@Override
public T remove(int index) {
T prev = this.list.remove(index);
if (prev != null) {
this.trackReferenceRemoved(prev);
}
return prev;
}
@Override
public int indexOf(Object o) {
return this.list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return this.list.lastIndexOf(o);
}
@Override
public ListIterator<T> listIterator() {
return this.listIterator(0);
}
@Override
public ListIterator<T> listIterator(int index) {
return new ListIterator<>() {
private final ListIterator<T> inner = HashedReferenceList.this.list.listIterator(index);
@Override
public boolean hasNext() {
return this.inner.hasNext();
}
@Override
public T next() {
return this.inner.next();
}
@Override
public boolean hasPrevious() {
return this.inner.hasPrevious();
}
@Override
public T previous() {
return this.inner.previous();
}
@Override
public int nextIndex() {
return this.inner.nextIndex();
}
@Override
public int previousIndex() {
return this.inner.previousIndex();
}
@Override
public void remove() {
int last = this.previousIndex();
if (last == -1) {
throw new NoSuchElementException();
}
T prev = HashedReferenceList.this.get(last);
if (prev != null) {
HashedReferenceList.this.trackReferenceRemoved(prev);
}
this.inner.remove();
}
@Override
public void set(T t) {
int last = this.previousIndex();
if (last == -1) {
throw new NoSuchElementException();
}
T prev = HashedReferenceList.this.get(last);
if (prev != t) {
if (prev != null) {
HashedReferenceList.this.trackReferenceRemoved(prev);
}
HashedReferenceList.this.trackReferenceAdded(t);
}
this.inner.remove();
}
@Override
public void add(T t) {
HashedReferenceList.this.trackReferenceAdded(t);
this.inner.add(t);
}
};
}
@Override
public List<T> subList(int fromIndex, int toIndex) {
return this.list.subList(fromIndex, toIndex);
}
private void trackReferenceAdded(T t) {
this.counter.addTo(t, 1);
}
@SuppressWarnings("unchecked")
private void trackReferenceRemoved(Object o) {
if (this.counter.addTo((T) o, -1) <= 1) {
this.counter.removeInt(o);
}
}
}
+2 -2
View File
@@ -9,8 +9,8 @@ pluginManagement {
}
plugins {
id("moe.luminolmc.hyacinthusweight.patcher") version weightVersion
id("moe.luminolmc.hyacinthusweight.core") version weightVersion
id("fun.bm.comfreyweight.patcher") version weightVersion
id("fun.bm.comfreyweight.core") version weightVersion
}
}