diff --git a/src/main/java/com/seibel/lod/core/enums/config/DistanceGenerationMode.java b/src/main/java/com/seibel/lod/core/enums/config/DistanceGenerationMode.java
index 712de3cc3..20e2b93e8 100644
--- a/src/main/java/com/seibel/lod/core/enums/config/DistanceGenerationMode.java
+++ b/src/main/java/com/seibel/lod/core/enums/config/DistanceGenerationMode.java
@@ -19,6 +19,8 @@
package com.seibel.lod.core.enums.config;
+import org.jetbrains.annotations.Nullable;
+
/**
* NONE
* BIOME_ONLY
@@ -92,4 +94,46 @@ public enum DistanceGenerationMode
{
this.complexity = complexity;
}
+
+ // Note: return null if out of range
+ @Nullable
+ public static DistanceGenerationMode previous(DistanceGenerationMode mode) {
+ switch (mode) {
+ case FULL:
+ return DistanceGenerationMode.FEATURES;
+ case FEATURES:
+ return DistanceGenerationMode.SURFACE;
+ case SURFACE:
+ return DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
+ case BIOME_ONLY_SIMULATE_HEIGHT:
+ return DistanceGenerationMode.BIOME_ONLY;
+ case BIOME_ONLY:
+ return DistanceGenerationMode.NONE;
+ case NONE:
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ // Note: return null if out of range
+ @Nullable
+ public static DistanceGenerationMode next(DistanceGenerationMode mode) {
+ switch (mode) {
+ case FULL:
+ return null;
+ case FEATURES:
+ return DistanceGenerationMode.FULL;
+ case SURFACE:
+ return DistanceGenerationMode.FEATURES;
+ case BIOME_ONLY_SIMULATE_HEIGHT:
+ return DistanceGenerationMode.SURFACE;
+ case BIOME_ONLY:
+ return DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
+ case NONE:
+ return DistanceGenerationMode.BIOME_ONLY;
+ default:
+ return null;
+ }
+ }
}
diff --git a/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java b/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java
index 9d82f9486..494f78620 100644
--- a/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java
+++ b/src/main/java/com/seibel/lod/core/enums/config/VerticalQuality.java
@@ -19,6 +19,8 @@
package com.seibel.lod.core.enums.config;
+import org.jetbrains.annotations.Nullable;
+
/**
* heightmap
* multi_lod
@@ -77,4 +79,34 @@ public enum VerticalQuality
{
this.maxVerticalData = maxVerticalData;
}
+
+ // Note: return null if out of range
+ @Nullable
+ public static VerticalQuality previous(VerticalQuality mode) {
+ switch (mode) {
+ case HIGH:
+ return VerticalQuality.MEDIUM;
+ case MEDIUM:
+ return VerticalQuality.LOW;
+ case LOW:
+ return null;
+ default:
+ return null;
+ }
+ }
+
+ // Note: return null if out of range
+ @Nullable
+ public static VerticalQuality next(VerticalQuality mode) {
+ switch (mode) {
+ case HIGH:
+ return null;
+ case MEDIUM:
+ return VerticalQuality.HIGH;
+ case LOW:
+ return VerticalQuality.MEDIUM;
+ default:
+ return null;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java
index 3c1362425..0f0297906 100644
--- a/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java
+++ b/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java
@@ -29,6 +29,7 @@ import java.util.concurrent.Executors;
import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
+import org.jetbrains.annotations.Nullable;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
@@ -100,6 +101,8 @@ public class LodDimensionFileHandler
+
+
//================//
// read from file //
//================//
@@ -116,125 +119,65 @@ public class LodDimensionFileHandler
for (byte tempDetailLevel = LodUtil.REGION_DETAIL_LEVEL; tempDetailLevel >= detailLevel; tempDetailLevel--)
{
- String fileName = getFileNameAndPathForRegion(regionX, regionZ, generationMode, tempDetailLevel, verticalQuality);
+ File file = getBestMatchingRegionFile(tempDetailLevel, regionX, regionZ, generationMode, verticalQuality);
+ if (file == null) continue; // Failed to find the file for this detail level. continue and try next one
- try
+ long fileSize = file.length();
+ if (fileSize == 0) continue; // file is empty. Let's not try parsing empty files
+ try (XZCompressorInputStream inputStream = new XZCompressorInputStream(new FileInputStream(file)))
{
- // if the fileName was null that means the folder is inaccessible
- // for some reason
- if (fileName == null)
- throw new IllegalArgumentException("Unable to read region [" + regionX + ", " + regionZ + "] file, no fileName.");
+ int fileVersion;
+ fileVersion = inputStream.read();
- File file = new File(fileName);
- if (!file.exists())
+ // check if this file can be read by this file handler
+ if (fileVersion < 6)
{
- //there is no file for current gen mode
- //search others above current from the most to the least detailed
- VerticalQuality tempVerticalQuality = VerticalQuality.HIGH;
- do {
- DistanceGenerationMode tempGenMode = DistanceGenerationMode.FULL;
- do {
- fileName = getFileNameAndPathForRegion(regionX, regionZ, tempGenMode, tempDetailLevel, verticalQuality);
- if (fileName != null)
- {
- file = new File(fileName);
- if (file.exists())
- break;
- }
- //decrease gen mode
- if (tempGenMode == DistanceGenerationMode.FULL)
- tempGenMode = DistanceGenerationMode.FEATURES;
- else if (tempGenMode == DistanceGenerationMode.FEATURES)
- tempGenMode = DistanceGenerationMode.SURFACE;
- else if (tempGenMode == DistanceGenerationMode.SURFACE)
- tempGenMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
- else if (tempGenMode == DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT)
- tempGenMode = DistanceGenerationMode.BIOME_ONLY;
- else if (tempGenMode == DistanceGenerationMode.BIOME_ONLY)
- tempGenMode = DistanceGenerationMode.NONE;
- } while (tempGenMode != generationMode);
- if (fileName != null)
- {
- file = new File(fileName);
- if (file.exists())
- break;
- }
- if (tempVerticalQuality == VerticalQuality.HIGH)
- tempVerticalQuality = VerticalQuality.MEDIUM;
- else if (tempVerticalQuality == VerticalQuality.MEDIUM)
- tempVerticalQuality = VerticalQuality.LOW;
- } while (tempVerticalQuality != verticalQuality);
- if (!file.exists())
- //there wasn't a file, don't return anything
- continue;
+ // the file we are reading is an older version,
+ // close the reader and delete the file.
+ inputStream.close();
+ file.delete();
+ ClientApi.LOGGER.info("Outdated LOD region file for region: (" + regionX + "," + regionZ + ")"
+ + " version found: " + fileVersion
+ + ", version requested: " + LOD_SAVE_FILE_VERSION
+ + ". File has been deleted.");
+ // This should not break, but be continue to see whether other detail levels can be loaded or updated
+ continue;
}
-
-
-
- // don't try parsing empty files
- long dataSize = file.length();
- dataSize -= 1;
- if (dataSize > 0)
+ else if (fileVersion > LOD_SAVE_FILE_VERSION)
{
- try (XZCompressorInputStream inputStream = new XZCompressorInputStream(new FileInputStream(file)))
- {
- int fileVersion;
- fileVersion = inputStream.read();
-
- // check if this file can be read by this file handler
- if (fileVersion < 6)
- {
- // the file we are reading is an older version,
- // close the reader and delete the file.
- inputStream.close();
- file.delete();
- ClientApi.LOGGER.info("Outdated LOD region file for region: (" + regionX + "," + regionZ + ")"
- + " version found: " + fileVersion
- + ", version requested: " + LOD_SAVE_FILE_VERSION
- + ". File was been deleted.");
- // This should not break, but be continue to see whether other versions can be loaded or updated
- continue;
- }
- else if (fileVersion > LOD_SAVE_FILE_VERSION)
- {
- // the file we are reading is a newer version,
- // close the reader and ignore the file, we don't
- // want to accidentally delete anything the user may want.
- inputStream.close();
- ClientApi.LOGGER.info("Newer LOD region file for region: (" + regionX + "," + regionZ + ")"
- + " version found: " + fileVersion
- + ", version requested: " + LOD_SAVE_FILE_VERSION
- + " this region will not be written to in order to protect the newer file.");
- // This should not break, but be continue to see whether other versions can be loaded or updated
- continue;
- }
- else if (fileVersion < LOD_SAVE_FILE_VERSION)
- {
- // this is old, but readable version
- // read and add the data to our region
- region.addLevelContainer(new VerticalLevelContainer(new DataInputStream(inputStream), fileVersion));
- inputStream.close();
- } else
- {
- // this file is a readable version,
- // read and add the data to our region
- region.addLevelContainer(new VerticalLevelContainer(new DataInputStream(inputStream), LOD_SAVE_FILE_VERSION));
- inputStream.close();
- }
- }
- catch (IOException ioEx)
- {
- ClientApi.LOGGER.error("LOD file read error. Unable to read to [" + fileName + "] error [" + ioEx.getMessage() + "]: ");
- ioEx.printStackTrace();
- }
+ // the file we are reading is a newer version,
+ // close the reader and ignore the file, we don't
+ // want to accidentally delete anything the user may want.
+ inputStream.close();
+ ClientApi.LOGGER.info("Newer LOD region file for region: (" + regionX + "," + regionZ + ")"
+ + " version found: " + fileVersion
+ + ", version requested: " + LOD_SAVE_FILE_VERSION
+ + " this region will not be written to in order to protect the newer file.");
+ // This should not break, but be continue to see whether other detail levels can be loaded or updated
+ continue;
+ }
+ else if (fileVersion < LOD_SAVE_FILE_VERSION)
+ {
+ ClientApi.LOGGER.debug("Old LOD region file for region: (" + regionX + "," + regionZ + ")"
+ + " version found: " + fileVersion
+ + ", version requested: " + LOD_SAVE_FILE_VERSION
+ + ". File will be loaded and updated to new format in next save.");
+ // this is old, but readable version
+ // read and add the data to our region
+ region.addLevelContainer(new VerticalLevelContainer(new DataInputStream(inputStream), fileVersion));
+ inputStream.close();
+ } else
+ {
+ // this file is a readable version,
+ // read and add the data to our region
+ region.addLevelContainer(new VerticalLevelContainer(new DataInputStream(inputStream), LOD_SAVE_FILE_VERSION));
+ inputStream.close();
}
}
- catch (Exception e)
+ catch (IOException ioEx)
{
- // the buffered reader encountered a
- // problem reading the file
- ClientApi.LOGGER.error("LOD file read error. Unable to read to [" + fileName + "] error [" + e.getMessage() + "]: ");
- e.printStackTrace();
+ ClientApi.LOGGER.error("LOD file read error. Unable to read xz compressed file [" + file + "] error [" + ioEx.getMessage() + "]: ");
+ ioEx.printStackTrace();
}
}// for each detail level
@@ -289,97 +232,102 @@ public class LodDimensionFileHandler
{
for (byte detailLevel = region.getMinDetailLevel(); detailLevel <= LodUtil.REGION_DETAIL_LEVEL; detailLevel++)
{
- String fileName = getFileNameAndPathForRegion(region.regionPosX, region.regionPosZ, region.getGenerationMode(), detailLevel, region.getVerticalQuality());
+ // Get the old file
+ File oldFile = getRegionFile(region.regionPosX, region.regionPosZ, region.getGenerationMode(), detailLevel, region.getVerticalQuality());
+ ClientApi.LOGGER.debug("saving region [" + region.regionPosX + ", " + region.regionPosZ + "] to file.");
- // if the fileName was null that means the folder is inaccessible
- // for some reason
- if (fileName == null)
+ boolean isFileFullyGened = false;
+ // make sure the file and folder exists
+ if (!oldFile.exists())
{
- ClientApi.LOGGER.warn("Unable to save region [" + region.regionPosX + ", " + region.regionPosZ + "] to file, file is inaccessible.");
- return;
- }
- File oldFile = new File(fileName);
- //ClientProxy.LOGGER.info("saving region [" + region.regionPosX + ", " + region.regionPosZ + "] to file.");
- //byte[] temp = region.getLevel(detailLevel).toDataString();
-
- try
- {
- boolean isFileFullyGened = false;
- // make sure the file and folder exists
- if (!oldFile.exists())
- {
- // the file doesn't exist,
- // create it and the folder if need be
- if (!oldFile.getParentFile().exists())
- oldFile.getParentFile().mkdirs();
+ // the file doesn't exist,
+ // create it and the folder if need be
+ if (!oldFile.getParentFile().exists())
+ oldFile.getParentFile().mkdirs();
+ try {
oldFile.createNewFile();
- }
- else
- {
- // the file exists, make sure it
- // is the correct version.
- // (to make sure we don't overwrite a newer
- // version file if it exists)
- int fileVersion = LOD_SAVE_FILE_VERSION;
- try (XZCompressorInputStream inputStream = new XZCompressorInputStream(new FileInputStream(oldFile)))
- {
- fileVersion = inputStream.read();
- inputStream.skip(1);
- isFileFullyGened = (inputStream.read() & 0b10000000) != 0;
- inputStream.close();
- }
- catch (IOException ex)
- {
- ex.printStackTrace();
- }
-
- // check if this file can be written to by the file handler
- if (fileVersion > LOD_SAVE_FILE_VERSION)
- {
- // the file we are reading is a newer version,
- // don't write anything, we don't want to accidentally
- // delete anything the user may want.
- continue;
- }
- // 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))
- {
- // add the version of this file
- outputStream.write(LOD_SAVE_FILE_VERSION);
-
- // add each LodChunk to the file
- boolean isLocalFullyGened = region.getLevel(detailLevel).writeData(new DataOutputStream(outputStream));
- outputStream.close();
-
- if (!isLocalFullyGened && isFileFullyGened)
- {
- // 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
- ClientApi.LOGGER.error("LOD file write error. Attempted to overwrite complete region with incomplete one [" + fileName + "]");
- try {
- newFile.delete();
- } catch (SecurityException e) {
- // Failed to delete temp file... just continue.
- }
- continue;
- }
-
- // overwrite the old file with the new one
- Files.move(newFile.toPath(), oldFile.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
- }
- catch (IOException ex)
- {
- ex.printStackTrace();
+ } catch (IOException e) {
+ ClientApi.LOGGER.error("LOD file write error. Unable to create parent directory for [" + oldFile + "] error [" + e.getMessage() + "]: ");
+ e.printStackTrace();
+ continue;
}
}
- catch (Exception e)
+ else
{
- ClientApi.LOGGER.error("LOD file write error. Unable to write to [" + fileName + "] error [" + e.getMessage() + "]: ");
+ // the file exists, make sure it
+ // is the correct version.
+ // (to make sure we don't overwrite a newer
+ // version file if it exists)
+ int fileVersion = LOD_SAVE_FILE_VERSION;
+ try (XZCompressorInputStream inputStream = new XZCompressorInputStream(new FileInputStream(oldFile)))
+ {
+ fileVersion = inputStream.read();
+ inputStream.skip(1);
+ isFileFullyGened = (inputStream.read() & 0b10000000) != 0;
+ inputStream.close();
+ }
+ catch (IOException e)
+ {
+ ClientApi.LOGGER.warn("LOD file write warning. Unable to read existing file [" + oldFile + "] version. Treating it as latest version. [" + e.getMessage() + "]: ");
+ e.printStackTrace();
+ }
+
+ // check if this file can be written to by the file handler
+ if (fileVersion > LOD_SAVE_FILE_VERSION)
+ {
+ // the file we are reading is a newer version,
+ // don't write anything, we don't want to accidentally
+ // delete anything the user may want.
+ continue;
+ }
+ // if we got this far then we are good
+ // to overwrite the old file
+ }
+
+ // Now create a new temporary save file
+ File tempFile;
+ try {
+ tempFile = File.createTempFile(oldFile.getName(), TMP_FILE_EXTENSION);
+ } catch (IOException e) {
+ ClientApi.LOGGER.error("LOD file write error. Unable to create temp file for [" + oldFile + "] error [" + e.getMessage() + "]: ");
+ e.printStackTrace();
+ continue;
+ }
+ tempFile.deleteOnExit(); // Mark it to be deleted on exit if any unexcepted terminations happen
+ try (XZCompressorOutputStream outputStream = new XZCompressorOutputStream(new FileOutputStream(tempFile), 3))
+ {
+ // add the version of this file
+ outputStream.write(LOD_SAVE_FILE_VERSION);
+ // add each LodChunk to the file
+ boolean isNewDataFullyGened = region.getLevel(detailLevel).writeData(new DataOutputStream(outputStream));
+ outputStream.close();
+
+ if (!isNewDataFullyGened && isFileFullyGened)
+ {
+ // 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
+ ClientApi.LOGGER.error("LOD file write error. Attempted to overwrite complete region with incomplete one [" + oldFile + "]");
+ try {
+ tempFile.delete();
+ } catch (SecurityException e) {
+ // Failed to delete temp file... just continue.
+ }
+ continue;
+ }
+ }
+ catch (IOException e)
+ {
+ ClientApi.LOGGER.error("LOD file write error. Unable to write to temp file [" + tempFile + "] error [" + e.getMessage() + "]: ");
+ e.printStackTrace();
+ continue;
+ }
+
+ // overwrite the old file with the new one
+ try {
+ Files.move(tempFile.toPath(), oldFile.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException e) {
+ ClientApi.LOGGER.error("LOD file write error. Unable to update file [" + oldFile + "] error [" + e.getMessage() + "]: ");
e.printStackTrace();
}
}
@@ -398,27 +346,40 @@ public class LodDimensionFileHandler
*
* Returns null if there is an IO or security Exception. */ - private String getFileNameAndPathForRegion(int regionX, int regionZ, DistanceGenerationMode generationMode, byte detailLevel, VerticalQuality verticalQuality) - { - try - { - // saveFolder is something like - // ".\Super Flat\DIM-1\data\" - // or - // ".\Super Flat\data\" - return dimensionDataSaveFolder.getCanonicalPath() + File.separatorChar + - verticalQuality + File.separatorChar + - generationMode.toString() + File.separatorChar + - DETAIL_FOLDER_NAME_PREFIX + detailLevel + File.separatorChar + - FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION; - } - catch (IOException | SecurityException e) - { - ClientApi.LOGGER.warn("Unable to get the filename for the region [" + regionX + ", " + regionZ + "], error: [" + e.getMessage() + "].\n" - + "One possible cause is that the process failed to read the current path location due to security config. Stacktrace: "); - e.printStackTrace(); - return null; + + private String getFileBasePath() { + try { + return dimensionDataSaveFolder.getCanonicalPath() + File.separatorChar; + } catch (IOException e) { + ClientApi.LOGGER.warn("Unable to get the base save file path. One possible cause is that" + + " the process failed to read the current path location due to security configs."); + throw new RuntimeException("DistantHorizons Get Save File Path Failure"); } } + private File getRegionFile(int regionX, int regionZ, DistanceGenerationMode genMode, byte detail, VerticalQuality vertQuality) { + return new File(getFileBasePath() + vertQuality + File.separatorChar + + genMode + File.separatorChar + + DETAIL_FOLDER_NAME_PREFIX + detail + File.separatorChar + + FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION); + } + + // Return null if no file found + @Nullable + private File getBestMatchingRegionFile(byte detailLevel, int regionX, int regionZ, DistanceGenerationMode targetGenMode, VerticalQuality targetVertQuality) { + DistanceGenerationMode genMode = targetGenMode; + // Search from least GenMode to max GenMode, than least vertQuality to max vertQuality + do { + File file = getRegionFile(regionX, regionZ, genMode, detailLevel, targetVertQuality); + if (file.exists()) return file; // Found target file. + targetGenMode = DistanceGenerationMode.next(targetGenMode); + if (targetGenMode == null) { // Failed to find any files for this vertQuality. Try next one up. + targetGenMode = genMode; + targetVertQuality = VerticalQuality.next(targetVertQuality); + } + } while (targetVertQuality != null); + return null; + } + + } diff --git a/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java b/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java index 9c2012f6c..5cf02a501 100644 --- a/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java +++ b/src/main/java/com/seibel/lod/core/util/ThreadMapUtil.java @@ -28,6 +28,8 @@ import java.util.concurrent.ConcurrentMap; import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.objects.VertexOptimizer; +// FIXME: Nuke this whole thing and use ThreadLocal instead. And no more redundant get() please! + /** * Holds data used by specific threads so * the data doesn't have to be recreated every @@ -116,7 +118,8 @@ public class ThreadMapUtil //________________________// - + + //TODO: Maybe use actual valid total world height instead of always assuming the worse and alloc 1024 blocks. /** returns the array filled with 0's */ public static long[] getBuilderVerticalArray(int detailLevel) { @@ -138,19 +141,19 @@ public class ThreadMapUtil /** returns the array filled with 0's */ public static long[] getVerticalDataArray(int arrayLength) { - if (!threadVerticalAddDataMap.containsKey(Thread.currentThread().getName()) || (threadVerticalAddDataMap.get(Thread.currentThread().getName()) == null)) + long[] array = threadVerticalAddDataMap.get(Thread.currentThread().getName()); + if (array == null || array.length != arrayLength) { - threadVerticalAddDataMap.put(Thread.currentThread().getName(), new long[arrayLength]); + array = new long[arrayLength]; + threadVerticalAddDataMap.put(Thread.currentThread().getName(), array); } else - { - Arrays.fill(threadVerticalAddDataMap.get(Thread.currentThread().getName()), 0); - } - return threadVerticalAddDataMap.get(Thread.currentThread().getName()); + Arrays.fill(array, 0); + return array; } - - + + //FIXME: If the arrayLength change, this may return incorrect sized array /** returns the array NOT cleared every time */ public static short[] getHeightAndDepth(int arrayLength) { @@ -165,18 +168,19 @@ public class ThreadMapUtil /** returns the array filled with 0's */ public static long[] getVerticalUpdateArray(int detailLevel) { - if (!verticalUpdate.containsKey(Thread.currentThread().getName()) || (verticalUpdate.get(Thread.currentThread().getName()) == null)) + long[][] arrays = verticalUpdate.get(Thread.currentThread().getName()); + if (arrays == null) { - long[][] array = new long[LodUtil.DETAIL_OPTIONS][]; - for (int i = 1; i < LodUtil.DETAIL_OPTIONS; i++) - array[i] = new long[DetailDistanceUtil.getMaxVerticalData(i - 1) * 4]; - verticalUpdate.put(Thread.currentThread().getName(), array); + arrays = new long[LodUtil.DETAIL_OPTIONS][]; + verticalUpdate.put(Thread.currentThread().getName(), arrays); } + long[] array = arrays[detailLevel]; + int arrayLength = DetailDistanceUtil.getMaxVerticalData(detailLevel) * 4; + if (array == null || array.length != arrayLength) + array = new long[arrayLength]; else - { - Arrays.fill(verticalUpdate.get(Thread.currentThread().getName())[detailLevel], 0); - } - return verticalUpdate.get(Thread.currentThread().getName())[detailLevel]; + Arrays.fill(array, 0); + return array; } /** clears all arrays so they will have to be rebuilt */