mirror of
https://github.com/PaperMC/Paper.git
synced 2024-09-12 06:58:11 +02:00
Upstream has released updates that appears to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: da08d022 SPIGOT-4700: Add PlayerFishEvent.State.REEL_IN 0cef14e4 Remove draft API from selectEntities CraftBukkit Changes:a46fdbc6
Remove outdated build delay.3697519b
SPIGOT-4708: Fix ExactChoice recipes neglecting material9ead7009
SPIGOT-4677: Add minecraft.admin.command_feedback permissionc3749a23
Remove the Damage tag from items when it is 0.f74c7b95
SPIGOT-4706: Can't interact with active item494eef45
Mention requirement of JIRA ticket for bug fixes51d62dec
SPIGOT-4702: Exception when middle clicking certain slotsbe557e69
SPIGOT-4700: Add PlayerFishEvent.State.REEL_IN
140 lines
6.8 KiB
Diff
140 lines
6.8 KiB
Diff
From 4c3edd05499f6111fd2b4feadc51ebb6a864be3d Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Sat, 11 Aug 2018 00:49:20 -0400
|
|
Subject: [PATCH] Detect and repair corrupt Region Files
|
|
|
|
If the file has partial data written but not the full 8192 bytes,
|
|
then the server will be unable to load that region file...
|
|
|
|
I don't know why mojang only checks for 4096, when anything less than 8192 is a crash.
|
|
|
|
But to be safe, it will attempt to back up the file.
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
|
index e2d4450e90..c20511588d 100644
|
|
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
|
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
|
@@ -25,10 +25,10 @@ public class RegionFile {
|
|
private static final boolean ENABLE_EXTENDED_SAVE = Boolean.parseBoolean(System.getProperty("net.minecraft.server.RegionFile.enableExtendedSave", "true"));
|
|
// Spigot end
|
|
private static final byte[] a = new byte[4096];
|
|
- private final File b;
|
|
- private RandomAccessFile c;
|
|
- private final int[] d = new int[1024];
|
|
- private final int[] e = new int[1024];
|
|
+ private final File b;private File getFile() { return b; } // Paper - OBFHELPER
|
|
+ private RandomAccessFile c;private RandomAccessFile getDataFile() { return c; } // Paper - OBFHELPER
|
|
+ private final int[] d = new int[1024];private int[] offsets = d; // Paper - OBFHELPER
|
|
+ private final int[] e = new int[1024];private int[] timestamps = e; // Paper - OBFHELPER
|
|
private List<Boolean> f;
|
|
private int g;
|
|
private long h;
|
|
@@ -43,7 +43,7 @@ public class RegionFile {
|
|
}
|
|
|
|
this.c = new RandomAccessFile(file, "rw");
|
|
- if (this.c.length() < 4096L) {
|
|
+ if (this.c.length() < 8192L) { // Paper - headers should be 8192
|
|
this.c.write(RegionFile.a);
|
|
this.c.write(RegionFile.a);
|
|
this.g += 8192;
|
|
@@ -93,22 +93,23 @@ public class RegionFile {
|
|
this.c.seek(j * 4 + 4); // Go back to where we were
|
|
}
|
|
}
|
|
- if (k != 0 && (k >> 8) + (length) <= this.f.size()) {
|
|
+ if (k > 0 && (k >> 8) > 1 && (k >> 8) + (k & 255) <= this.f.size()) { // Paper >= 1 as 0/1 are the headers, and negative isnt valid
|
|
for (int l = 0; l < (length); ++l) {
|
|
// Spigot end
|
|
this.f.set((k >> 8) + l, false);
|
|
}
|
|
}
|
|
// Spigot start
|
|
- else if (length > 0) {
|
|
- org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Invalid chunk: ({0}, {1}) Offset: {2} Length: {3} runs off end file. {4}", new Object[]{j % 32, (int) (j / 32), k >> 8, length, file});
|
|
+ else if (k != 0) { // Paper
|
|
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Invalid chunk: ({0}, {1}) Offset: {2} Length: {3} runs off end file. {4}", new Object[]{j % 32, (int) (j / 32), k >> 8, length, file}); // Paper
|
|
+ deleteChunk(j); // Paper
|
|
}
|
|
// Spigot end
|
|
}
|
|
|
|
for (j = 0; j < 1024; ++j) {
|
|
k = headerAsInts.get(); // Paper
|
|
- this.e[j] = k;
|
|
+ if (offsets[j] != 0) this.timestamps[j] = k; // Paper - don't set timestamp if it got 0'd above due to corruption
|
|
}
|
|
} catch (IOException ioexception) {
|
|
ioexception.printStackTrace();
|
|
@@ -144,10 +145,10 @@ public class RegionFile {
|
|
int j1 = this.c.readInt();
|
|
|
|
if (j1 > 4096 * i1) {
|
|
- org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Invalid chunk: ({0}, {1}) Offset: {2} Invalid Size: {3}>{4} {5}", new Object[]{i, j, l, j1, i1 * 4096, this.b}); // Spigot
|
|
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Invalid chunk: ({0}, {1}) Offset: {2} Invalid Size: {3}>{4} {5}", new Object[]{i, j, l, j1, i1 * 4096, this.b}); // Spigot
|
|
return null;
|
|
} else if (j1 <= 0) {
|
|
- org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.WARNING, "Invalid chunk: ({0}, {1}) Offset: {2} Invalid Size: {3} {4}", new Object[]{i, j, l, j1, this.b}); // Spigot
|
|
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Invalid chunk: ({0}, {1}) Offset: {2} Invalid Size: {3} {4}", new Object[]{i, j, l, j1, this.b}); // Spigot
|
|
return null;
|
|
} else {
|
|
byte b0 = this.c.readByte();
|
|
@@ -327,6 +328,54 @@ public class RegionFile {
|
|
|
|
}
|
|
|
|
+ // Paper start
|
|
+ public synchronized void deleteChunk(int j1) {
|
|
+ backup();
|
|
+ int k = offsets[j1];
|
|
+ int x = j1 & 1024;
|
|
+ int z = j1 >> 2;
|
|
+ int offset = (k >> 8);
|
|
+ int len = (k & 255);
|
|
+ String debug = "idx:" + + j1 + " - " + x + "," + z + " - offset: " + offset + " - len: " + len;
|
|
+ try {
|
|
+ timestamps[j1] = 0;
|
|
+ offsets[j1] = 0;
|
|
+ RandomAccessFile file = getDataFile();
|
|
+ file.seek(j1 * 4);
|
|
+ file.writeInt(0);
|
|
+ // clear the timestamp
|
|
+ file.seek(4096 + j1 * 4);
|
|
+ file.writeInt(0);
|
|
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Deleted corrupt chunk (" + debug + ") " + getFile().getAbsolutePath(), e);
|
|
+ } catch (IOException e) {
|
|
+
|
|
+ org.bukkit.Bukkit.getLogger().log(java.util.logging.Level.SEVERE, "Error deleting corrupt chunk (" + debug + ") " + getFile().getAbsolutePath(), e);
|
|
+ }
|
|
+ }
|
|
+ private boolean backedUp = false;
|
|
+ private synchronized void backup() {
|
|
+ if (backedUp) {
|
|
+ return;
|
|
+ }
|
|
+ backedUp = true;
|
|
+ File file = this.getFile();
|
|
+ java.text.DateFormat formatter = new java.text.SimpleDateFormat("yyyy-MM-dd");
|
|
+ java.util.Date today = new java.util.Date();
|
|
+ File corrupt = new File(file.getParentFile(), file.getName() + "." + formatter.format(today) + ".corrupt");
|
|
+ if (corrupt.exists()) {
|
|
+ return;
|
|
+ }
|
|
+ org.apache.logging.log4j.Logger logger = org.apache.logging.log4j.LogManager.getLogger();
|
|
+ logger.error("Region file " + file.getAbsolutePath() + " was corrupt. Backing up to " + corrupt.getAbsolutePath() + " and repairing");
|
|
+ try {
|
|
+ java.nio.file.Files.copy(file.toPath(), corrupt.toPath());
|
|
+
|
|
+ } catch (IOException e) {
|
|
+ logger.error("Error backing up corrupt file" + file.getAbsolutePath(), e);
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
+
|
|
class ChunkBuffer extends ByteArrayOutputStream {
|
|
|
|
private final int b;
|
|
--
|
|
2.21.0
|
|
|