From 9ef9823b3bcaf404afa02ea6ac413ee74129ed90 Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Tue, 19 Feb 2019 22:30:00 +1100 Subject: [PATCH] Allow Reading Old Large Chunks The size of chunks in the region format is overdetermined. In particular their size on disk is indicated by both a sector count in the header, and actual size in the body. If their size would overflow the header field (>= 255 sectors), it can just be read directly from the body instead. This code/concept was adapted from MinecraftForge. By: md_5 --- .../level/chunk/storage/RegionFile.java.patch | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/level/chunk/storage/RegionFile.java.patch b/paper-server/patches/sources/net/minecraft/world/level/chunk/storage/RegionFile.java.patch index 3aa820298..601f408a8 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/chunk/storage/RegionFile.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/chunk/storage/RegionFile.java.patch @@ -25,7 +25,33 @@ int i = this.file.read(this.header, 0L); if (i != -1) { -@@ -132,7 +133,7 @@ +@@ -89,6 +90,14 @@ + if (l != 0) { + int i1 = RegionFile.getSectorNumber(l); + int j1 = RegionFile.getNumSectors(l); ++ // Spigot start ++ if (j1 == 255) { ++ // We're maxed out, so we need to read the proper length from the section ++ ByteBuffer realLen = ByteBuffer.allocate(4); ++ this.file.read(realLen, i1 * 4096); ++ j1 = (realLen.getInt(0) + 4) / 4096 + 1; ++ } ++ // Spigot end + + if (i1 < 2) { + RegionFile.LOGGER.warn("Region file {} has invalid sector at index: {}; sector {} overlaps with header", new Object[]{path, k, i1}); +@@ -128,11 +137,18 @@ + } else { + int j = RegionFile.getSectorNumber(i); + int k = RegionFile.getNumSectors(i); ++ // Spigot start ++ if (k == 255) { ++ ByteBuffer realLen = ByteBuffer.allocate(4); ++ this.file.read(realLen, j * 4096); ++ k = (realLen.getInt(0) + 4) / 4096 + 1; ++ } ++ // Spigot end + int l = k * 4096; ByteBuffer bytebuffer = ByteBuffer.allocate(l); this.file.read(bytebuffer, (long) (j * 4096)); @@ -34,7 +60,7 @@ if (bytebuffer.remaining() < 5) { RegionFile.LOGGER.error("Chunk {} header is truncated: expected {} but read {}", new Object[]{pos, l, bytebuffer.remaining()}); return null; -@@ -246,7 +247,7 @@ +@@ -246,7 +262,7 @@ try { this.file.read(bytebuffer, (long) (j * 4096)); @@ -43,7 +69,7 @@ if (bytebuffer.remaining() != 5) { return false; } else { -@@ -349,7 +350,7 @@ +@@ -349,7 +365,7 @@ bytebuffer.putInt(1); bytebuffer.put((byte) (this.version.getId() | 128)); @@ -52,7 +78,7 @@ return bytebuffer; } -@@ -358,7 +359,7 @@ +@@ -358,7 +374,7 @@ FileChannel filechannel = FileChannel.open(path1, StandardOpenOption.CREATE, StandardOpenOption.WRITE); try { @@ -61,7 +87,7 @@ filechannel.write(buf); } catch (Throwable throwable) { if (filechannel != null) { -@@ -382,7 +383,7 @@ +@@ -382,7 +398,7 @@ } private void writeHeader() throws IOException { @@ -70,7 +96,7 @@ this.file.write(this.header, 0L); } -@@ -418,7 +419,7 @@ +@@ -418,7 +434,7 @@ if (i != j) { ByteBuffer bytebuffer = RegionFile.PADDING_BUFFER.duplicate();