From 5762c41f1ad06fe6dc6a063dc5b59e04ae1d7aea Mon Sep 17 00:00:00 2001 From: cola98765 Date: Mon, 1 Nov 2021 10:18:49 +0100 Subject: [PATCH] protect full regions against being overwritten by a partial one --- .../lod/handlers/LodDimensionFileHandler.java | 16 ++++++++++--- .../lod/objects/VerticalLevelContainer.java | 23 ++++++++++++------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java index 33a172570..cc516d922 100644 --- a/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java @@ -289,6 +289,7 @@ public class LodDimensionFileHandler } File oldFile = new File(fileName); //ClientProxy.LOGGER.info("saving region [" + region.regionPosX + ", " + region.regionPosZ + "] to file."); + byte[] temp = region.getLevel(detailLevel).toDataString(); try { @@ -308,9 +309,12 @@ public class LodDimensionFileHandler // (to make sure we don't overwrite a newer // version file if it exists) int fileVersion = LOD_SAVE_FILE_VERSION; + int isFull = 0; try (XZCompressorInputStream inputStream = new XZCompressorInputStream(new FileInputStream(oldFile))) { fileVersion = inputStream.read(); + inputStream.skip(1); + isFull = inputStream.read() & 0b10000000; inputStream.close(); } catch (IOException ex) @@ -326,11 +330,17 @@ public class LodDimensionFileHandler // delete anything the user may want. return; } - + if ((temp[1] & 0b10000000) != 0b10000000 && isFull == 0b10000000) + { + // existing file is complete while new one is only partially generate + // this can happen is for some reason loading failed + // this doesn't fix the bug, but at least protects old data + ClientProxy.LOGGER.error("LOD file write error. Attempted to overwrite complete region with incomplete one [" + fileName + "]"); + return; + } // if we got this far then we are good // to overwrite the old file } - // the old file is good, now create a new temporary save file File newFile = new File(fileName + TMP_FILE_EXTENSION); try (XZCompressorOutputStream outputStream = new XZCompressorOutputStream(new FileOutputStream(newFile), 3)) @@ -339,7 +349,7 @@ public class LodDimensionFileHandler outputStream.write(LOD_SAVE_FILE_VERSION); // add each LodChunk to the file - outputStream.write(region.getLevel(detailLevel).toDataString()); + outputStream.write(temp); outputStream.close(); // overwrite the old file with the new one diff --git a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java index f692baa1d..01cb97756 100644 --- a/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java +++ b/src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java @@ -129,7 +129,7 @@ public class VerticalLevelContainer implements LevelContainer long newData; detailLevel = inputData[index]; index++; - maxVerticalData = inputData[index]; + maxVerticalData = inputData[index] & 0b01111111; index++; size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel); int x = size * size * maxVerticalData; @@ -181,24 +181,31 @@ public class VerticalLevelContainer implements LevelContainer public byte[] toDataString() { int index = 0; - int x = size * size * maxVerticalData; + int x = size * size; int tempIndex; long current; - + boolean allGenerated = true; byte[] tempData = ThreadMapUtil.getSaveContainer(detailLevel); tempData[index] = detailLevel; index++; tempData[index] = (byte) maxVerticalData; index++; - + int j; for (int i = 0; i < x; i++) { - current = dataContainer[i]; - for (tempIndex = 0; tempIndex < 8; tempIndex++) - tempData[index + tempIndex] = (byte) (current >>> (8 * tempIndex)); - index += 8; + for (j = 0; j < maxVerticalData; j++) + { + current = dataContainer[i * maxVerticalData + j]; + for (tempIndex = 0; tempIndex < 8; tempIndex++) + tempData[index + tempIndex] = (byte) (current >>> (8 * tempIndex)); + index += 8; + } + if(!DataPointUtil.doesItExist(dataContainer[i])) + allGenerated = false; } + if (allGenerated) + tempData[1] |= 0b10000000; return tempData; }