Linear flusher (#88)

* Linear flusher

* Use a queue & a single thread

* Customizable flusher thread number

* Use try statements
This commit is contained in:
Sofiane H. Djerbi
2023-08-07 03:04:31 +02:00
committed by GitHub
parent 1271516e58
commit 042f11d759
15 changed files with 246 additions and 195 deletions

View File

@@ -5,18 +5,15 @@ Subject: [PATCH] Region format configuration
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index 7da7e0aeb5eac9ac73a3570e716f1ceb11fd7027..b86c90cc3601e666998cfa12f44515f605bb53eb 100644
index 7da7e0aeb5eac9ac73a3570e716f1ceb11fd7027..f08bcc9ae1770fa847d8a5e873a554bef5485100 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -192,4 +192,10 @@ public class KaiijuConfig {
@@ -192,4 +192,7 @@ public class KaiijuConfig {
}
return builder.build();
}
+
+ public static boolean regionFormatDebug = false;
+
+ private static void regionFormatSettings() {
+ regionFormatDebug = getBoolean("region-format.debug", regionFormatDebug);
+ }
}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuWorldConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuWorldConfig.java
@@ -85,7 +82,7 @@ index 0000000000000000000000000000000000000000..7164d9cd03186f0657783f83de3d6435
+ }
+}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index cc1a7c4d38874ec218f7151685ae6cc00295c2e4..06233380f7580726753de34c1fb23d6347c9ac94 100644
index 7e5645d9cb64ce17f60c85619f5640c8de4b1e86..bc9204d2c925437e9ff5c5d62d9faf38c2938e48 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -893,7 +893,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa

View File

@@ -38,6 +38,34 @@ index f2c27e0ac65be4b75c1d86ef6fd45fdb538d96ac..00724993d0448454d14a47652b039b88
public static final class InProgressWrite {
public long writeCounter;
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index f08bcc9ae1770fa847d8a5e873a554bef5485100..b7f43cce80742aa0cd523e930772ff84946f3eef 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -15,7 +15,6 @@ import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -193,6 +192,15 @@ public class KaiijuConfig {
return builder.build();
}
+ public static int linearFlushFrequency = 10;
+ public static int linearFlushThreads = 1;
+
private static void regionFormatSettings() {
+ linearFlushFrequency = getInt("region-format.linear.flush-frequency", linearFlushFrequency);
+ linearFlushThreads = getInt("region-format.linear.flush-max-threads", linearFlushThreads);
+ if (linearFlushThreads < 0)
+ linearFlushThreads = Math.max(Runtime.getRuntime().availableProcessors() + linearFlushThreads, 1);
+ else
+ linearFlushThreads = Math.max(linearFlushThreads, 1);
}
}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/AbstractRegionFile.java b/src/main/java/dev/kaiijumc/kaiiju/region/AbstractRegionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..249303116d3cfadd078ebf0ae6e44bf99eed6a47
@@ -112,10 +140,10 @@ index 0000000000000000000000000000000000000000..dcfbabf54b19a4c29d5c95830242c5c2
+}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4bf89d0727
index 0000000000000000000000000000000000000000..e40989889f3821bb7484fc0bae5d94b033013904
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFile.java
@@ -0,0 +1,337 @@
@@ -0,0 +1,316 @@
+package dev.kaiijumc.kaiiju.region;
+
+import com.github.luben.zstd.ZstdInputStream;
@@ -138,65 +166,57 @@ index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4b
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class LinearRegionFile extends Thread implements AbstractRegionFile {
+public class LinearRegionFile implements AbstractRegionFile, AutoCloseable {
+ private static final long SUPERBLOCK = -4323716122432332390L;
+ private static final byte VERSION = 2;
+ private static final int HEADER_SIZE = 32;
+ private static final int FOOTER_SIZE = 8;
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final List<Byte> SUPPORTED_VERSIONS = Arrays.asList((byte) 1, (byte) 2);
+
+ private static final LinearRegionFileFlusher linearRegionFileFlusher = new LinearRegionFileFlusher();
+
+ private final byte[][] buffer = new byte[1024][];
+ private final int[] bufferUncompressedSize = new int[1024];
+
+ private final int[] chunkTimestamps = new int[1024];
+ private final Object markedToSaveLock = new Object();
+ private final ChunkStatus[] statuses = new ChunkStatus[1024];
+
+ private final LZ4Compressor compressor;
+ private final LZ4FastDecompressor decompressor;
+
+ private boolean markedToSave = false;
+ private boolean close = false;
+
+ public final ReentrantLock fileLock = new ReentrantLock(true);
+ public Path regionFile;
+
+ private final int compressionLevel;
+
+ public Path getRegionFile() {
+ return this.regionFile;
+ }
+ private AtomicBoolean markedToSave = new AtomicBoolean(false);
+ public boolean closed = false;
+ public Path path;
+
+ public ReentrantLock getFileLock() {
+ return this.fileLock;
+ }
+
+ public LinearRegionFile(Path file, int compression) throws IOException {
+ this.regionFile = file;
+ this.path = file;
+ this.compressionLevel = compression;
+
+ this.compressor = LZ4Factory.fastestInstance().fastCompressor();
+ this.decompressor = LZ4Factory.fastestInstance().fastDecompressor();
+
+ File regionFile = new File(this.regionFile.toString());
+ File regionFile = new File(this.path.toString());
+
+ Arrays.fill(this.bufferUncompressedSize, 0);
+
+ if(regionFile.canRead()) {
+ FileInputStream fileStream = new FileInputStream(regionFile);
+ DataInputStream rawDataStream = new DataInputStream(fileStream);
+ if (!regionFile.canRead()) return;
+
+ try (FileInputStream fileStream = new FileInputStream(regionFile);
+ DataInputStream rawDataStream = new DataInputStream(fileStream)) {
+
+ long superBlock = rawDataStream.readLong();
+ if (superBlock != SUPERBLOCK)
+ throw new RuntimeException("Invalid superblock: " + superBlock + " file " + file);
+ throw new RuntimeException("Invalid superblock: " + superBlock + " in " + file);
+
+ byte version = rawDataStream.readByte();
+ if (!SUPPORTED_VERSIONS.contains(version))
+ throw new RuntimeException("Invalid version: " + version + " file " + file);
+ throw new RuntimeException("Invalid version: " + version + " in " + file);
+
+ // Skip newestTimestamp (Long) + Compression level (Byte) + Chunk count (Short): Unused.
+ rawDataStream.skipBytes(11);
@@ -204,7 +224,7 @@ index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4b
+ int dataCount = rawDataStream.readInt();
+ long fileLength = file.toFile().length();
+ if (fileLength != HEADER_SIZE + dataCount + FOOTER_SIZE)
+ throw new IOException("Invalid file length: " + this.regionFile + " " + fileLength + " " + (HEADER_SIZE + dataCount + FOOTER_SIZE));
+ throw new IOException("Invalid file length: " + this.path + " " + fileLength + " " + (HEADER_SIZE + dataCount + FOOTER_SIZE));
+
+ rawDataStream.skipBytes(8); // Skip data hash (Long): Unused.
+
@@ -213,133 +233,124 @@ index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4b
+
+ superBlock = rawDataStream.readLong();
+ if (superBlock != SUPERBLOCK)
+ throw new IOException("Footer superblock invalid " + this.regionFile);
+ throw new IOException("Footer superblock invalid " + this.path);
+
+ DataInputStream dataStream = new DataInputStream(new ZstdInputStream(new ByteArrayInputStream(rawCompressed)));
+ try (DataInputStream dataStream = new DataInputStream(new ZstdInputStream(new ByteArrayInputStream(rawCompressed)))) {
+
+ int[] starts = new int[1024];
+ for(int i = 0; i < 1024; i++) {
+ starts[i] = dataStream.readInt();
+ dataStream.skipBytes(4); // Skip timestamps (Int): Unused.
+ }
+
+ for(int i = 0; i < 1024; i++) {
+ if(starts[i] > 0) {
+ int size = starts[i];
+ byte[] b = new byte[size];
+ dataStream.readFully(b, 0, size);
+
+ int maxCompressedLength = this.compressor.maxCompressedLength(size);
+ byte[] compressed = new byte[maxCompressedLength];
+ int compressedLength = this.compressor.compress(b, 0, size, compressed, 0, maxCompressedLength);
+ b = new byte[compressedLength];
+ System.arraycopy(compressed, 0, b, 0, compressedLength);
+
+ this.buffer[i] = b;
+ this.bufferUncompressedSize[i] = size;
+ int[] starts = new int[1024];
+ for (int i = 0; i < 1024; i++) {
+ starts[i] = dataStream.readInt();
+ dataStream.skipBytes(4); // Skip timestamps (Int): Unused.
+ }
+ }
+ }
+ this.start();
+ }
+
+ private synchronized void markToSave() {
+ synchronized(markedToSaveLock) {
+ markedToSave = true;
+ }
+ }
+ for (int i = 0; i < 1024; i++) {
+ if (starts[i] > 0) {
+ int size = starts[i];
+ byte[] b = new byte[size];
+ dataStream.readFully(b, 0, size);
+
+ private synchronized boolean isMarkedToSave() {
+ synchronized(markedToSaveLock) {
+ if(markedToSave) {
+ markedToSave = false;
+ return true;
+ }
+ return false;
+ }
+ }
+ int maxCompressedLength = this.compressor.maxCompressedLength(size);
+ byte[] compressed = new byte[maxCompressedLength];
+ int compressedLength = this.compressor.compress(b, 0, size, compressed, 0, maxCompressedLength);
+ b = new byte[compressedLength];
+ System.arraycopy(compressed, 0, b, 0, compressedLength);
+
+ public void run() {
+ try {
+ while(true) {
+ if(markedToSave) {
+ try {
+ flush();
+ } catch(IOException ex) {
+ LOGGER.error("Region file " + this.regionFile.toAbsolutePath() + " flush failed");
+ this.buffer[i] = b;
+ this.bufferUncompressedSize[i] = size;
+ }
+ }
+ for(int i = 0 ; i < 100 ; i++) {
+ Thread.sleep(100);
+ if(close) return;
+ }
+ }
+ } catch(InterruptedException ignored) {}
+ }
+ }
+
+ public synchronized boolean doesChunkExist(ChunkPos pos) throws Exception {
+ public Path getRegionFile() {
+ return this.path;
+ }
+
+ public ReentrantLock getFileLock() {
+ return this.fileLock;
+ }
+
+ public void flush() throws IOException {
+ if (isMarkedToSave()) flushWrapper(); // sync
+ }
+
+ private void markToSave() {
+ linearRegionFileFlusher.scheduleSave(this);
+ markedToSave.set(true);
+ }
+
+ public boolean isMarkedToSave() {
+ return markedToSave.getAndSet(false);
+ }
+
+ public void flushWrapper() {
+ try {
+ save();
+ } catch (IOException e) {
+ LOGGER.error("Failed to flush region file " + path.toAbsolutePath(), e);
+ }
+ }
+
+ public boolean doesChunkExist(ChunkPos pos) throws Exception {
+ throw new Exception("doesChunkExist is a stub");
+ }
+
+ public synchronized void flush() throws IOException {
+ if(!isMarkedToSave()) return;
+
+ private synchronized void save() throws IOException {
+ long timestamp = getTimestamp();
+ short chunkCount = 0;
+
+ File tempFile = new File(regionFile.toString() + ".tmp");
+ FileOutputStream fileStream = new FileOutputStream(tempFile);
+ File tempFile = new File(path.toString() + ".tmp");
+
+ ByteArrayOutputStream zstdByteArray = new ByteArrayOutputStream();
+ ZstdOutputStream zstdStream = new ZstdOutputStream(zstdByteArray, this.compressionLevel);
+ zstdStream.setChecksum(true);
+ DataOutputStream zstdDataStream = new DataOutputStream(zstdStream);
+ DataOutputStream dataStream = new DataOutputStream(fileStream);
+ try (FileOutputStream fileStream = new FileOutputStream(tempFile);
+ ByteArrayOutputStream zstdByteArray = new ByteArrayOutputStream();
+ ZstdOutputStream zstdStream = new ZstdOutputStream(zstdByteArray, this.compressionLevel);
+ DataOutputStream zstdDataStream = new DataOutputStream(zstdStream);
+ DataOutputStream dataStream = new DataOutputStream(fileStream)) {
+
+ dataStream.writeLong(SUPERBLOCK);
+ dataStream.writeByte(VERSION);
+ dataStream.writeLong(timestamp);
+ dataStream.writeByte(this.compressionLevel);
+ dataStream.writeLong(SUPERBLOCK);
+ dataStream.writeByte(VERSION);
+ dataStream.writeLong(timestamp);
+ dataStream.writeByte(this.compressionLevel);
+
+ ArrayList<byte[]> byteBuffers = new ArrayList<>();
+ for(int i = 0; i < 1024; i++) {
+ if(this.bufferUncompressedSize[i] != 0) {
+ chunkCount += 1;
+ byte[] content = new byte[bufferUncompressedSize[i]];
+ this.decompressor.decompress(buffer[i], 0, content, 0, bufferUncompressedSize[i]);
+ ArrayList<byte[]> byteBuffers = new ArrayList<>();
+ for (int i = 0; i < 1024; i++) {
+ if (this.bufferUncompressedSize[i] != 0) {
+ chunkCount += 1;
+ byte[] content = new byte[bufferUncompressedSize[i]];
+ this.decompressor.decompress(buffer[i], 0, content, 0, bufferUncompressedSize[i]);
+
+ byteBuffers.add(content);
+ } else byteBuffers.add(null);
+ byteBuffers.add(content);
+ } else byteBuffers.add(null);
+ }
+ for (int i = 0; i < 1024; i++) {
+ zstdDataStream.writeInt(this.bufferUncompressedSize[i]); // Write uncompressed size
+ zstdDataStream.writeInt(this.chunkTimestamps[i]); // Write timestamp
+ }
+ for (int i = 0; i < 1024; i++) {
+ if (byteBuffers.get(i) != null)
+ zstdDataStream.write(byteBuffers.get(i), 0, byteBuffers.get(i).length);
+ }
+ zstdDataStream.close();
+
+ dataStream.writeShort(chunkCount);
+
+ byte[] compressed = zstdByteArray.toByteArray();
+
+ dataStream.writeInt(compressed.length);
+ dataStream.writeLong(0);
+
+ dataStream.write(compressed, 0, compressed.length);
+ dataStream.writeLong(SUPERBLOCK);
+
+ dataStream.flush();
+ fileStream.getFD().sync();
+ fileStream.getChannel().force(true); // Ensure atomicity on Btrfs
+ }
+ for(int i = 0; i < 1024; i++) {
+ zstdDataStream.writeInt(this.bufferUncompressedSize[i]); // Write uncompressed size
+ zstdDataStream.writeInt(this.chunkTimestamps[i]); // Write timestamp
+ }
+ for(int i = 0; i < 1024; i++) {
+ if(byteBuffers.get(i) != null)
+ zstdDataStream.write(byteBuffers.get(i), 0, byteBuffers.get(i).length);
+ }
+ zstdDataStream.close();
+
+ dataStream.writeShort(chunkCount);
+
+ byte[] compressed = zstdByteArray.toByteArray();
+
+ dataStream.writeInt(compressed.length);
+ dataStream.writeLong(0);
+
+ dataStream.write(compressed, 0, compressed.length);
+ dataStream.writeLong(SUPERBLOCK);
+
+ dataStream.flush();
+ fileStream.getFD().sync();
+ fileStream.getChannel().force(true); // Ensure atomicity on Btrfs
+ dataStream.close();
+
+ fileStream.close();
+ Files.move(tempFile.toPath(), this.regionFile, StandardCopyOption.REPLACE_EXISTING);
+ Files.move(tempFile.toPath(), this.path, StandardCopyOption.REPLACE_EXISTING);
+ }
+
+
+ public void setStatus(int x, int z, ChunkStatus status) {
+ this.statuses[getChunkIndex(x, z)] = status;
+ }
@@ -360,7 +371,7 @@ index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4b
+ this.chunkTimestamps[index] = getTimestamp();
+ this.bufferUncompressedSize[getChunkIndex(pos.x, pos.z)] = uncompressedSize;
+ } catch (IOException e) {
+ LOGGER.error("Chunk write IOException " + e + " " + this.regionFile);
+ LOGGER.error("Chunk write IOException " + e + " " + this.path);
+ }
+ markToSave();
+ }
@@ -370,7 +381,6 @@ index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4b
+ }
+
+ private class ChunkBuffer extends ByteArrayOutputStream {
+
+ private final ChunkPos pos;
+
+ public ChunkBuffer(ChunkPos chunkcoordintpair) {
@@ -423,12 +433,9 @@ index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4b
+ }
+
+ public void close() throws IOException {
+ close = true;
+ try {
+ flush();
+ } catch(IOException e) {
+ throw new IOException("Region flush IOException " + e + " " + this.regionFile);
+ }
+ if (closed) return;
+ closed = true;
+ flush(); // sync
+ }
+
+ private static int getChunkIndex(int x, int z) {
@@ -446,13 +453,64 @@ index 0000000000000000000000000000000000000000..b7ce89429675bde7f037793305275f4b
+ public void setOversized(int x, int z, boolean something) {}
+
+ public CompoundTag getOversizedData(int x, int z) throws IOException {
+ throw new IOException("getOversizedData is a stub " + this.regionFile);
+ throw new IOException("getOversizedData is a stub " + this.path);
+ }
+
+ public boolean isOversized(int x, int z) {
+ return false;
+ }
+}
diff --git a/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java
new file mode 100644
index 0000000000000000000000000000000000000000..a5731e37aa63004476dd6db67191d5be6ce480be
--- /dev/null
+++ b/src/main/java/dev/kaiijumc/kaiiju/region/LinearRegionFileFlusher.java
@@ -0,0 +1,45 @@
+package dev.kaiijumc.kaiiju.region;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.util.Queue;
+import java.util.concurrent.*;
+import dev.kaiijumc.kaiiju.KaiijuConfig;
+import org.bukkit.Bukkit;
+
+public class LinearRegionFileFlusher {
+ private final Queue<LinearRegionFile> savingQueue = new LinkedBlockingQueue<>();
+ private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(
+ new ThreadFactoryBuilder()
+ .setNameFormat("linear-flush-scheduler")
+ .build()
+ );
+ private final ExecutorService executor = Executors.newFixedThreadPool(
+ KaiijuConfig.linearFlushThreads,
+ new ThreadFactoryBuilder()
+ .setNameFormat("linear-flusher-%d")
+ .build()
+ );
+
+ public LinearRegionFileFlusher() {
+ Bukkit.getLogger().info("Using " + KaiijuConfig.linearFlushThreads + " threads for linear region flushing.");
+ scheduler.scheduleAtFixedRate(this::pollAndFlush, 0L, KaiijuConfig.linearFlushFrequency, TimeUnit.SECONDS);
+ }
+
+ public void scheduleSave(LinearRegionFile regionFile) {
+ if (savingQueue.contains(regionFile)) return;
+ savingQueue.add(regionFile);
+ }
+
+ private void pollAndFlush() {
+ while (!savingQueue.isEmpty()) {
+ LinearRegionFile regionFile = savingQueue.poll();
+ if (!regionFile.closed && regionFile.isMarkedToSave())
+ executor.execute(regionFile::flushWrapper);
+ }
+ }
+
+ public void shutdown() {
+ executor.shutdown();
+ scheduler.shutdown();
+ }
+}
diff --git a/src/main/java/io/papermc/paper/chunk/system/io/RegionFileIOThread.java b/src/main/java/io/papermc/paper/chunk/system/io/RegionFileIOThread.java
index 8a11e10b01fa012b2f98b1c193c53251e848f909..61001e76b38f8647b33e73b5cc15b4b6785cf49a 100644
--- a/src/main/java/io/papermc/paper/chunk/system/io/RegionFileIOThread.java
@@ -587,7 +645,7 @@ index 25fe439c8d1e88a86e85ac9a4761425d98ee6c4f..c4d28d887b4cc71dc713b1e3f46bc80f
regionFile.setStatus(chunkPos.x, chunkPos.z, ChunkSerializer.getStatus(compound));
}
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 042ca6b3faae5249210567f2c26dff404974e1ff..7099a44a2322ab390c21e74668c8657dcc9e5e87 100644
index 042ca6b3faae5249210567f2c26dff404974e1ff..1446db0111ba21514640e09e48a32d54b4a97a0c 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -426,8 +426,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
@@ -596,7 +654,7 @@ index 042ca6b3faae5249210567f2c26dff404974e1ff..7099a44a2322ab390c21e74668c8657d
- public EntityRegionFileStorage(Path directory, boolean dsync) {
- super(directory, dsync);
+ public EntityRegionFileStorage(String format, int linearCompression, Path directory, boolean dsync) { // Kaiiju
+ public EntityRegionFileStorage(dev.kaiijumc.kaiiju.region.RegionFileFormat format, int linearCompression, Path directory, boolean dsync) { // Kaiiju
+ super(format, linearCompression, directory, dsync); // Kaiiju
}
@@ -754,7 +812,7 @@ index dcfe090c269d4cbcc2eb1b6f85392848bb34656c..d42c320179ae055b8675d1ce6ce1788e
try (DataInputStream out = new DataInputStream(new java.io.BufferedInputStream(new InflaterInputStream(Files.newInputStream(file))))) {
return NbtIo.read((java.io.DataInput) out);
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823f4b63a3a 100644
index 81554c321a78258ff78da3801f00d0fb90b9e113..e91e8aef8b63ea9d94e0ecb3e4a62655a8c77ce1 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -22,9 +22,13 @@ public class RegionFileStorage implements AutoCloseable {
@@ -836,7 +894,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
}
// Paper end
return regionfile;
@@ -126,28 +134,49 @@ public class RegionFileStorage implements AutoCloseable {
@@ -126,28 +134,45 @@ public class RegionFileStorage implements AutoCloseable {
}
// Paper end - cache regionfile does not exist state
if (this.regionCache.size() >= io.papermc.paper.configuration.GlobalConfiguration.get().misc.regionFileCacheSize) { // Paper - configurable
@@ -874,10 +932,6 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
+ // Kaiiju end
this.createRegionFile(regionPos);
}
+ // Kaiiju start - Polyglot
+ if (dev.kaiijumc.kaiiju.KaiijuConfig.regionFormatDebug)
+ org.bukkit.Bukkit.getLogger().info("Opening file " + path1 + " with format " + this.format + " (existingOnly = " + existingOnly + ")");
+ // Kaiiju end
+
// Paper end - cache regionfile does not exist state
FileUtil.createDirectoriesSafe(this.folder); // Paper - only create directory if not existing only - moved from above
@@ -893,7 +947,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
}
// Paper end
return regionfile1;
@@ -175,7 +204,7 @@ public class RegionFileStorage implements AutoCloseable {
@@ -175,7 +200,7 @@ public class RegionFileStorage implements AutoCloseable {
}
@@ -902,7 +956,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
synchronized (regionfile) {
try (DataInputStream datainputstream = regionfile.getChunkDataInputStream(chunkCoordinate)) {
CompoundTag oversizedData = regionfile.getOversizedData(chunkCoordinate.x, chunkCoordinate.z);
@@ -222,14 +251,14 @@ public class RegionFileStorage implements AutoCloseable {
@@ -222,14 +247,14 @@ public class RegionFileStorage implements AutoCloseable {
@Nullable
public CompoundTag read(ChunkPos pos) throws IOException {
// CraftBukkit start - SPIGOT-5680: There's no good reason to preemptively create files on read, save that for writing
@@ -919,7 +973,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
// We add the regionfile parameter to avoid the potential deadlock (on fileLock) if we went back to obtain a regionfile
// if we decide to re-read
// Paper end
@@ -239,7 +268,7 @@ public class RegionFileStorage implements AutoCloseable {
@@ -239,7 +264,7 @@ public class RegionFileStorage implements AutoCloseable {
// Paper start
if (regionfile.isOversized(pos.x, pos.z)) {
@@ -928,7 +982,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
return readOversizedChunk(regionfile, pos);
}
// Paper end
@@ -253,12 +282,12 @@ public class RegionFileStorage implements AutoCloseable {
@@ -253,12 +278,12 @@ public class RegionFileStorage implements AutoCloseable {
if (this.isChunkData) {
ChunkPos chunkPos = ChunkSerializer.getChunkCoordinate(nbttagcompound);
if (!chunkPos.equals(pos)) {
@@ -944,7 +998,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
return null;
}
}
@@ -292,13 +321,13 @@ public class RegionFileStorage implements AutoCloseable {
@@ -292,13 +317,13 @@ public class RegionFileStorage implements AutoCloseable {
return nbttagcompound;
} finally { // Paper start
@@ -960,7 +1014,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
if (regionfile == null) {
return;
}
@@ -328,7 +357,7 @@ public class RegionFileStorage implements AutoCloseable {
@@ -328,7 +353,7 @@ public class RegionFileStorage implements AutoCloseable {
}
protected void write(ChunkPos pos, @Nullable CompoundTag nbt) throws IOException {
@@ -969,7 +1023,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
if (nbt == null && regionfile == null) {
return;
}
@@ -378,7 +407,7 @@ public class RegionFileStorage implements AutoCloseable {
@@ -378,7 +403,7 @@ public class RegionFileStorage implements AutoCloseable {
}
// Paper end
} finally { // Paper start
@@ -978,7 +1032,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
} // Paper end
}
@@ -387,7 +416,7 @@ public class RegionFileStorage implements AutoCloseable {
@@ -387,7 +412,7 @@ public class RegionFileStorage implements AutoCloseable {
ObjectIterator objectiterator = this.regionCache.values().iterator();
while (objectiterator.hasNext()) {
@@ -987,7 +1041,7 @@ index 81554c321a78258ff78da3801f00d0fb90b9e113..b35a6a7daf768af3bc453fe18deec823
try {
regionfile.close();
@@ -403,7 +432,7 @@ public class RegionFileStorage implements AutoCloseable {
@@ -403,7 +428,7 @@ public class RegionFileStorage implements AutoCloseable {
ObjectIterator objectiterator = this.regionCache.values().iterator();
while (objectiterator.hasNext()) {

View File

@@ -5,12 +5,12 @@ Subject: [PATCH] Network configuration
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index b86c90cc3601e666998cfa12f44515f605bb53eb..7c6d43d8a360530344ef296f4477750c8a298607 100644
index b7f43cce80742aa0cd523e930772ff84946f3eef..fa829cef4033625470dfae29ddf777e6c5ab8c55 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -198,4 +198,7 @@ public class KaiijuConfig {
private static void regionFormatSettings() {
regionFormatDebug = getBoolean("region-format.debug", regionFormatDebug);
@@ -203,4 +203,7 @@ public class KaiijuConfig {
else
linearFlushThreads = Math.max(linearFlushThreads, 1);
}
+
+ private static void networkSettings() {

View File

@@ -6,12 +6,12 @@ Subject: [PATCH] Send null entity packets
This is from Purpur. Don't send null entity packets.
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index 7c6d43d8a360530344ef296f4477750c8a298607..ab08e11f13921163b8ff1ff51ff9e9b86d2b47c7 100644
index fa829cef4033625470dfae29ddf777e6c5ab8c55..47e23a196ae5e44600a64184b69141c00235baca 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -198,7 +198,10 @@ public class KaiijuConfig {
private static void regionFormatSettings() {
regionFormatDebug = getBoolean("region-format.debug", regionFormatDebug);
@@ -203,7 +203,10 @@ public class KaiijuConfig {
else
linearFlushThreads = Math.max(linearFlushThreads, 1);
}
+
+ public static boolean sendNullEntityPackets = true;
@@ -21,7 +21,7 @@ index 7c6d43d8a360530344ef296f4477750c8a298607..ab08e11f13921163b8ff1ff51ff9e9b8
}
}
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 6670e657e08e130f7e0368f418379fd1ece00cdf..5558d87ef182f82be7877455dd027082c6a80632 100644
index 81d0b2933040a451441f660f9e46199ae3b111e3..cdbc4be679d7e096c1005eaf84b74c4877479c43 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -201,6 +201,11 @@ public class ServerEntity {

View File

@@ -7,10 +7,10 @@ Don't kick players because 1 keepalive is lost.
This patch is from Purpur.
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index ab08e11f13921163b8ff1ff51ff9e9b86d2b47c7..b42a3466f145a92608c8746fd4beb529b4a60b01 100644
index 47e23a196ae5e44600a64184b69141c00235baca..95b53b50606ea0ad47f407bebbb9e2bd445c0e66 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -200,8 +200,10 @@ public class KaiijuConfig {
@@ -205,8 +205,10 @@ public class KaiijuConfig {
}
public static boolean sendNullEntityPackets = true;

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Optimization Configuration
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index b42a3466f145a92608c8746fd4beb529b4a60b01..7b56cc1275319cf07a4a25280e0ff900bdca8afa 100644
index 95b53b50606ea0ad47f407bebbb9e2bd445c0e66..8aab072a21b0775338b8235a84f5f675f385cf37 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -206,4 +206,7 @@ public class KaiijuConfig {
@@ -211,4 +211,7 @@ public class KaiijuConfig {
sendNullEntityPackets = getBoolean("network.send-null-entity-packets", sendNullEntityPackets);
alternateKeepAlive = getBoolean("network.alternate-keepalive", alternateKeepAlive);
}

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Gameplay Configuration
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index 7b56cc1275319cf07a4a25280e0ff900bdca8afa..fdc4cdbf34ed10f6523dceac7c1931d3ca4eb522 100644
index 8aab072a21b0775338b8235a84f5f675f385cf37..46ae5b84ee5b87b0ed0b93e920689e44288a50d2 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -209,4 +209,7 @@ public class KaiijuConfig {
@@ -214,4 +214,7 @@ public class KaiijuConfig {
private static void optimizationSettings() {
}

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Server mod name
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index fdc4cdbf34ed10f6523dceac7c1931d3ca4eb522..e1f50adfa216320bc53b460d11666064cb58c969 100644
index 46ae5b84ee5b87b0ed0b93e920689e44288a50d2..778de435ca3c13ccc2f2d86030e3529436a2d945 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -210,6 +210,9 @@ public class KaiijuConfig {
@@ -215,6 +215,9 @@ public class KaiijuConfig {
private static void optimizationSettings() {
}
@@ -19,7 +19,7 @@ index fdc4cdbf34ed10f6523dceac7c1931d3ca4eb522..e1f50adfa216320bc53b460d11666064
}
}
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 06233380f7580726753de34c1fb23d6347c9ac94..1b3f895b51b634ee9cf69cdbbfd7a1e600de16f0 100644
index bc9204d2c925437e9ff5c5d62d9faf38c2938e48..5168d16b7e9ed08bdedd0e386f9671a63b6859be 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1812,7 +1812,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa

View File

@@ -64,14 +64,14 @@ index c4d28d887b4cc71dc713b1e3f46bc80f4484a95d..f50507ab85282d261985ce9b186581f5
// Paper start
this.dataRegionManager = new io.papermc.paper.chunk.SingleThreadChunkRegionManager(this.level, 2, (1.0 / 3.0), 1, 6, "Data", DataRegionData::new, DataRegionSectionData::new);
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 7099a44a2322ab390c21e74668c8657dcc9e5e87..475554797ffc279243ac0d88f1e619c3dd07bc4b 100644
index 1446db0111ba21514640e09e48a32d54b4a97a0c..475554797ffc279243ac0d88f1e619c3dd07bc4b 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -426,8 +426,8 @@ public class ServerLevel extends Level implements WorldGenLevel {
private static final class EntityRegionFileStorage extends net.minecraft.world.level.chunk.storage.RegionFileStorage {
- public EntityRegionFileStorage(String format, int linearCompression, Path directory, boolean dsync) { // Kaiiju
- public EntityRegionFileStorage(dev.kaiijumc.kaiiju.region.RegionFileFormat format, int linearCompression, Path directory, boolean dsync) { // Kaiiju
- super(format, linearCompression, directory, dsync); // Kaiiju
+ public EntityRegionFileStorage(dev.kaiijumc.kaiiju.region.RegionFileFormat format, int linearCompression, boolean linearCrashOnBrokenSymlink, Path directory, boolean dsync) { // Kaiiju
+ super(format, linearCompression, linearCrashOnBrokenSymlink, directory, dsync); // Kaiiju
@@ -135,7 +135,7 @@ index 1d880f27dd147da683fc30ed6f1bfa43ecdb7d93..41598adf6d49a44bcaadfff379722146
}
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
index b35a6a7daf768af3bc453fe18deec823f4b63a3a..8409293b3f329715d6dff3d455c6a484d5b133ee 100644
index e91e8aef8b63ea9d94e0ecb3e4a62655a8c77ce1..bbc6a0c70cbafbfa411ab418e4fec11ad101ae91 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFileStorage.java
@@ -20,6 +20,7 @@ import net.minecraft.world.level.ChunkPos;
@@ -209,7 +209,7 @@ index b35a6a7daf768af3bc453fe18deec823f4b63a3a..8409293b3f329715d6dff3d455c6a484
+ guardAgainstBrokenSymlinks(path1); // Kaiiju - Crash on broken symlink
this.createRegionFile(regionPos);
}
// Kaiiju start - Polyglot
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java
index 9394d191c56aab78e63fd3f283efedd69384e323..dcfe4a285cc5865be3b0c1b8104b722895135dd0 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Toggle shared random for players
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index e1f50adfa216320bc53b460d11666064cb58c969..c934341c17caf4696065ac6c39bdfef570c62f13 100644
index 778de435ca3c13ccc2f2d86030e3529436a2d945..cac747a46cccf8b115917a72340e9b81e7a437c9 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -211,8 +211,10 @@ public class KaiijuConfig {
@@ -216,8 +216,10 @@ public class KaiijuConfig {
}
public static String serverModName = "Kaiiju";
@@ -20,7 +20,7 @@ index e1f50adfa216320bc53b460d11666064cb58c969..c934341c17caf4696065ac6c39bdfef5
}
}
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 27b57db24587337ccdce29e492052ca419863323..fc6279a39fd5e1bd02b2d9e77f451cd9ba1baf78 100644
index ee15661227754149164893d6acf678d13b2e1b27..0c50b516d0ff1c2812a877b57148f01861f8027f 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -566,6 +566,11 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Option to disable vanish api
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index c934341c17caf4696065ac6c39bdfef570c62f13..f49510c999ce5241f26dc9ba90a6148bf31467c7 100644
index cac747a46cccf8b115917a72340e9b81e7a437c9..a3c15f1009dad095b9411242e2d0347a6141984b 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -207,7 +207,10 @@ public class KaiijuConfig {
@@ -212,7 +212,10 @@ public class KaiijuConfig {
alternateKeepAlive = getBoolean("network.alternate-keepalive", alternateKeepAlive);
}

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Option to disable player stats
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index f49510c999ce5241f26dc9ba90a6148bf31467c7..b23f2df433d7ebc871f4009081c28ed9054d91c7 100644
index a3c15f1009dad095b9411242e2d0347a6141984b..8c872b2ad341f0105275209201fda03706535161 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -208,9 +208,11 @@ public class KaiijuConfig {
@@ -213,9 +213,11 @@ public class KaiijuConfig {
}
public static boolean disableVanishApi = false;

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Option to disable arm swing event
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index b23f2df433d7ebc871f4009081c28ed9054d91c7..ec71f3f52cb8f7931aabd94619d2e7a24491d7ad 100644
index 8c872b2ad341f0105275209201fda03706535161..9b118a6e22264c88c0460016822b1920631fff85 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -209,10 +209,12 @@ public class KaiijuConfig {
@@ -214,10 +214,12 @@ public class KaiijuConfig {
public static boolean disableVanishApi = false;
public static boolean disablePlayerStats = false;

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Option to disable ensure tick thread checks
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index ec71f3f52cb8f7931aabd94619d2e7a24491d7ad..fa2a763e5784e7dae02c94a13751cbf746b6eee8 100644
index 9b118a6e22264c88c0460016822b1920631fff85..95015955a8076bc903c012704b57b1b84286aaae 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -210,11 +210,13 @@ public class KaiijuConfig {
@@ -215,11 +215,13 @@ public class KaiijuConfig {
public static boolean disableVanishApi = false;
public static boolean disablePlayerStats = false;
public static boolean disableArmSwingEvent = false;

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Don't kick player on bad packet
diff --git a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
index fa2a763e5784e7dae02c94a13751cbf746b6eee8..ebfa9e1dcca5ea8272e796f0409902d92b59ee76 100644
index 95015955a8076bc903c012704b57b1b84286aaae..6df1720159383c2f536b40ded1092a437c1a20af 100644
--- a/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
+++ b/src/main/java/dev/kaiijumc/kaiiju/KaiijuConfig.java
@@ -201,10 +201,12 @@ public class KaiijuConfig {
@@ -206,10 +206,12 @@ public class KaiijuConfig {
public static boolean sendNullEntityPackets = true;
public static boolean alternateKeepAlive = false;