ForgePatch/patches/minecraft/net/minecraft/world/chunk/storage/RegionFile.java.patch

103 lines
4.4 KiB
Diff

--- a/net/minecraft/world/chunk/storage/RegionFile.java
+++ b/net/minecraft/world/chunk/storage/RegionFile.java
@@ -33,6 +33,7 @@
private final IntBuffer field_76716_d;
private final IntBuffer field_227127_h_;
private final RegionBitmap field_227128_i_ = new RegionBitmap();
+ private final Path filePath;
public RegionFile(File p_i225784_1_, File p_i225784_2_) throws IOException {
this(p_i225784_1_.toPath(), p_i225784_2_.toPath(), RegionFileVersion.field_227159_b_);
@@ -40,6 +41,7 @@
public RegionFile(Path p_i225785_1_, Path p_i225785_2_, RegionFileVersion p_i225785_3_) throws IOException {
this.field_227125_e_ = p_i225785_3_;
+ this.filePath = p_i225785_1_;
if (!Files.isDirectory(p_i225785_2_)) {
throw new IllegalArgumentException("Expected directory, got " + p_i225785_2_.toAbsolutePath());
} else {
@@ -62,6 +64,8 @@
if (k != 0) {
int l = func_227142_b_(k);
int i1 = func_227131_a_(k);
+ if (i1 == 255)
+ i1 = forgeGetRealLength(j, l);
this.field_227128_i_.func_227120_a_(l, i1);
}
}
@@ -70,6 +74,66 @@
}
}
+ private int forgeGetRealLength(int index, int offset) throws IOException {
+ int chunkX = index & 31;
+ int chunkZ = (index >> 5) & 31;
+
+ ByteBuffer header = ByteBuffer.allocate(5);
+ this.field_76719_c.read(header, offset * 4096);
+ ((Buffer)header).flip();
+
+ if (header.remaining() < 5) {
+ field_227122_a_.error("Chunk {},{} in {} header is truncated: expected 5 but read {}", chunkX, chunkZ, this.filePath.getFileName(), header.remaining());
+ return 255;
+ }
+
+ return (header.getInt() + 4) / 4096 + 1;
+ }
+
+ /**
+ * In 1.14, Forge added support for large chunks by allowing it to overflow the 255 section limit.
+ * Deferring the section size to the 'length' header in front of the chunk data.
+ * In 1.15, Mojang solved this issue by adding an external '.mcc' file for large chunks.
+ * Here, we attempt to detect and extract these large chunks from Forge's format to Vanilla's
+ */
+ public RegionFile extractLargeChunks(ChunkPos pos) throws IOException {
+ ChunkPos regionBase = new ChunkPos(pos.func_222241_h() * 32, pos.func_222242_i() * 32);
+ for (int index = 0; index < 1024; index++) {
+ int offset = this.field_76716_d.get(index);
+ if (func_227131_a_(offset) != 255) //If it's not 255, then it's not possible to be a oversized chunk. Move on.
+ continue;
+ offset = func_227142_b_(offset);
+
+ ChunkPos chunk = new ChunkPos(regionBase.field_77276_a + (index & 31), regionBase.field_77275_b + ((index >> 5) & 31));
+
+ ByteBuffer header = ByteBuffer.allocate(5);
+ this.field_76719_c.read(header, offset * 4096);
+ ((Buffer)header).flip();
+
+ if (header.remaining() < 5) {
+ field_227122_a_.error("Chunk {} in {} header is truncated: expected 5 but read {}", chunk, this.filePath.getFileName(), header.remaining());
+ continue;
+ }
+
+ int length = header.getInt();
+ byte version = header.get();
+ int sectors = (length + 4) / 4096 + 1;
+ if (sectors <= 255 || func_227130_a_(version))
+ continue; //Not over sized, or already external
+
+ ByteBuffer data = ByteBuffer.allocate(length + 4);
+ this.field_76719_c.read(data, offset * 4096);
+ ((Buffer)data).flip();
+
+ if (data.remaining() < length + 4) {
+ field_227122_a_.error("Chunk {} in {} is truncated: expected {} but read {}", chunk, this.filePath.getFileName(), length + 4, data.remaining());
+ continue;
+ }
+ func_227135_a_(chunk, data); //Save the chunk data, it'll be spit out to an external file.
+ }
+ return this;
+ }
+
private Path func_227145_e_(ChunkPos p_227145_1_) {
String s = "c." + p_227145_1_.field_77276_a + "." + p_227145_1_.field_77275_b + ".mcc";
return this.field_227124_d_.resolve(s);
@@ -225,6 +289,7 @@
int j = this.field_76716_d.get(i);
int k = func_227142_b_(j);
int l = func_227131_a_(j);
+ if (l == 255) l = forgeGetRealLength(i, k); //Forge: Old Forge fix, get real length, so we can free if needed
int i1 = p_227135_2_.remaining();
int j1 = func_227144_c_(i1);
int k1;