protect full regions against being overwritten by a partial one

This commit is contained in:
cola98765
2021-11-01 10:18:49 +01:00
parent dee9fa793d
commit 5762c41f1a
2 changed files with 28 additions and 11 deletions
@@ -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
@@ -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;
}