Add/Fix issue with writeData and Cut causing data loss
This commit is contained in:
@@ -23,6 +23,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
@@ -228,42 +229,35 @@ public class LodBuilder
|
||||
if (MC.getWrappedClientWorld() == null)
|
||||
return false;
|
||||
|
||||
// determine how many LODs to generate horizontally
|
||||
|
||||
byte minDetailLevel = region.getMinDetailLevel();
|
||||
HorizontalResolution detail = DetailDistanceUtil.getLodGenDetail(minDetailLevel);
|
||||
|
||||
|
||||
// determine how many LODs to generate vertically
|
||||
//VerticalQuality verticalQuality = LodConfig.CLIENT.graphics.qualityOption.verticalQuality.get();
|
||||
byte detailLevel = detail.detailLevel;
|
||||
|
||||
|
||||
// generate the LODs
|
||||
int posX;
|
||||
int posZ;
|
||||
for (int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++)
|
||||
{
|
||||
startX = detail.startX[i];
|
||||
startZ = detail.startZ[i];
|
||||
region.isWriting++;
|
||||
try {
|
||||
LodRegion newRegion = lodDim.getRegionFromFile(region, (byte)0, region.getGenerationMode(), region.getVerticalQuality());
|
||||
assert(region==newRegion);
|
||||
|
||||
long[] data;
|
||||
long[] dataToMergeVertical = createVerticalDataToMerge(detail, chunk, config, startX, startZ);
|
||||
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.WORLD_HEIGHT / 2 + 1, DetailDistanceUtil.getMaxVerticalData(detailLevel));
|
||||
|
||||
|
||||
//lodDim.clear(detailLevel, posX, posZ);
|
||||
if (data != null && data.length != 0)
|
||||
// generate the LODs
|
||||
int posX;
|
||||
int posZ;
|
||||
for (int i = 0; i < 16*16; i++)
|
||||
{
|
||||
posX = LevelPosUtil.convert((byte) 0, chunk.getChunkPosX() * 16 + startX, minDetailLevel);
|
||||
posZ = LevelPosUtil.convert((byte) 0, chunk.getChunkPosZ() * 16 + startZ, minDetailLevel);
|
||||
long oldData = lodDim.getSingleData(minDetailLevel, posX, posZ);
|
||||
if (override || !DataPointUtil.doesItExist(oldData) ||
|
||||
DataPointUtil.getGenerationMode(oldData)<config.distanceGenerationMode.complexity) {
|
||||
lodDim.addVerticalData(minDetailLevel, posX, posZ, data);
|
||||
lodDim.updateData(minDetailLevel, posX, posZ);
|
||||
startX = i/16;
|
||||
startZ = i%16;
|
||||
|
||||
long[] data;
|
||||
long[] dataToMergeVertical = createVerticalDataToMerge((byte)0, chunk, config, startX, startZ);
|
||||
data = DataPointUtil.mergeMultiData(dataToMergeVertical, DataPointUtil.WORLD_HEIGHT / 2 + 1, DetailDistanceUtil.getMaxVerticalData((byte)0));
|
||||
|
||||
if (data != null && data.length != 0)
|
||||
{
|
||||
posX = chunk.getChunkPosX() * 16 + startX;
|
||||
posZ = chunk.getChunkPosZ() * 16 + startZ;
|
||||
if (region.addVerticalData((byte)0, posX, posZ, data, override))
|
||||
region.updateArea((byte)0, posX, posZ);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
region.isWriting--;
|
||||
}
|
||||
return true;
|
||||
//executeTime = System.currentTimeMillis() - executeTime;
|
||||
@@ -271,12 +265,12 @@ public class LodBuilder
|
||||
}
|
||||
|
||||
/** creates a vertical DataPoint */
|
||||
private long[] createVerticalDataToMerge(HorizontalResolution detail, IChunkWrapper chunk, LodBuilderConfig config, int startX, int startZ)
|
||||
private long[] createVerticalDataToMerge(byte detail, IChunkWrapper chunk, LodBuilderConfig config, int startX, int startZ)
|
||||
{
|
||||
// equivalent to 2^detailLevel
|
||||
int size = 1 << detail.detailLevel;
|
||||
int size = 1 << detail;
|
||||
|
||||
long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray(detail.detailLevel);
|
||||
long[] dataToMerge = ThreadMapUtil.getBuilderVerticalArray(detail);
|
||||
int verticalData = DataPointUtil.WORLD_HEIGHT / 2 + 1;
|
||||
int height;
|
||||
int depth;
|
||||
|
||||
@@ -235,10 +235,11 @@ public class LodDimensionFileHandler
|
||||
for (int j = 0; j < lodDimension.getWidth(); j++)
|
||||
{
|
||||
LodRegion r = lodDimension.getRegionByArrayIndex(i, j);
|
||||
|
||||
|
||||
// FIXME: Note that the isWriting is a crude attempt at syncing. It won't work.
|
||||
// It just reduce the chance of race condition
|
||||
if (r != null && r.needSaving)
|
||||
{
|
||||
r.needSaving = false;
|
||||
regionToSave.put(r.getRegionPos(), r);
|
||||
}
|
||||
}
|
||||
@@ -288,10 +289,12 @@ public class LodDimensionFileHandler
|
||||
// this for loop should be safe and loop until all values are gone.
|
||||
while (!regionToSave.isEmpty()) {
|
||||
for (LodRegion r : regionToSave.values()) {
|
||||
//Check if the data has been swapped out right under me. Otherwise remove it from the entry
|
||||
if (!regionToSave.remove(r.getRegionPos(), r)) continue;
|
||||
try
|
||||
{
|
||||
r.isWriting++;
|
||||
try {
|
||||
if (r.isWriting>1) continue;
|
||||
//Check if the data has been swapped out right under me. Otherwise remove it from the entry
|
||||
if (!regionToSave.remove(r.getRegionPos(), r)) continue;
|
||||
r.needSaving = false;
|
||||
Instant i = Instant.now();
|
||||
ClientApi.LOGGER.info("Lod: Saving Region "+r.getRegionPos());
|
||||
saveRegionToFile(r);
|
||||
@@ -302,6 +305,8 @@ public class LodDimensionFileHandler
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
r.isWriting--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public interface LevelContainer
|
||||
* @param posZ z position in the detail level
|
||||
* @return true if correctly added, false otherwise
|
||||
*/
|
||||
boolean addVerticalData(long[] data, int posX, int posZ);
|
||||
boolean addVerticalData(long[] data, int posX, int posZ, boolean override);
|
||||
|
||||
/**
|
||||
* With this you can add data to the level container
|
||||
|
||||
@@ -354,19 +354,18 @@ public class LodDimension
|
||||
int regionZ;
|
||||
int minDistance;
|
||||
byte detail;
|
||||
byte minAllowedDetailLevel;
|
||||
regionX = (x + center.x) - halfWidth;
|
||||
regionZ = (z + center.z) - halfWidth;
|
||||
LodRegion region = regions[x][z];
|
||||
if (region != null) {
|
||||
if (region != null && !region.needSaving && region.isWriting==0) {
|
||||
// check what detail level this region should be
|
||||
// and cut it if it is higher then that
|
||||
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ,
|
||||
playerPosX, playerPosZ);
|
||||
detail = DetailDistanceUtil.getTreeCutDetailFromDistance(minDistance);
|
||||
minAllowedDetailLevel = DetailDistanceUtil.getCutLodDetail(detail);
|
||||
if (region.getMinDetailLevel() < minAllowedDetailLevel) {
|
||||
region.cutTree(minAllowedDetailLevel);
|
||||
if (region.getMinDetailLevel() < detail) {
|
||||
if (region.needSaving) return; // FIXME: A crude attempt at lowering chance of race condition!
|
||||
region.cutTree(detail);
|
||||
region.needRegenBuffer = 2;
|
||||
regenDimensionBuffers = true;
|
||||
}
|
||||
@@ -408,6 +407,7 @@ public class LodDimension
|
||||
regionZ = (z + center.z) - halfWidth;
|
||||
final RegionPos regionPos = new RegionPos(regionX, regionZ);
|
||||
region = regions[x][z];
|
||||
if (region != null && region.isWriting!=0) return; // FIXME: A crude attempt at lowering chance of race condition!
|
||||
|
||||
minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionX, regionZ, playerPosX,
|
||||
playerPosZ);
|
||||
@@ -451,7 +451,7 @@ public class LodDimension
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinate it will be overwritten.
|
||||
*/
|
||||
public Boolean addVerticalData(byte detailLevel, int posX, int posZ, long[] data)
|
||||
public Boolean addVerticalData(byte detailLevel, int posX, int posZ, long[] data, boolean override)
|
||||
{
|
||||
int regionPosX = LevelPosUtil.getRegion(detailLevel, posX);
|
||||
int regionPosZ = LevelPosUtil.getRegion(detailLevel, posZ);
|
||||
@@ -461,10 +461,8 @@ public class LodDimension
|
||||
if (region == null)
|
||||
return false;
|
||||
|
||||
boolean nodeAdded = region.addVerticalData(detailLevel, posX, posZ, data);
|
||||
boolean nodeAdded = region.addVerticalData(detailLevel, posX, posZ, data, override);
|
||||
if (nodeAdded) {
|
||||
region.needRegenBuffer = 2;
|
||||
region.needSaving = true;
|
||||
regenDimensionBuffers = true;
|
||||
}
|
||||
return nodeAdded;
|
||||
@@ -575,22 +573,6 @@ public class LodDimension
|
||||
return region.getSingleData(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
/** Clears the given region */
|
||||
public void clear(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
int xRegion = LevelPosUtil.getRegion(detailLevel, posX);
|
||||
int zRegion = LevelPosUtil.getRegion(detailLevel, posZ);
|
||||
LodRegion region = getRegion(xRegion, zRegion);
|
||||
if (region == null)
|
||||
return;
|
||||
region.clear(detailLevel, posX, posZ);
|
||||
region.needRegenBuffer = 2;
|
||||
regenDimensionBuffers = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the buffer at the given array index needs
|
||||
* to have its buffer regenerated. Also decrease the state by 1
|
||||
|
||||
@@ -70,6 +70,7 @@ public class LodRegion {
|
||||
|
||||
public volatile int needRegenBuffer = 2;
|
||||
public volatile boolean needSaving = false;
|
||||
public volatile int isWriting = 0;
|
||||
|
||||
public LodRegion(byte minDetailLevel, RegionPos regionPos, DistanceGenerationMode generationMode,
|
||||
VerticalQuality verticalQuality) {
|
||||
@@ -94,6 +95,7 @@ public class LodRegion {
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data) {
|
||||
assert(isWriting!=0);
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
|
||||
@@ -114,7 +116,8 @@ public class LodRegion {
|
||||
*
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addVerticalData(byte detailLevel, int posX, int posZ, long[] data) {
|
||||
public boolean addVerticalData(byte detailLevel, int posX, int posZ, long[] data, boolean override) {
|
||||
assert(isWriting!=0);
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
|
||||
@@ -123,7 +126,12 @@ public class LodRegion {
|
||||
if (this.dataContainer[detailLevel] == null)
|
||||
return false;// this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
|
||||
return this.dataContainer[detailLevel].addVerticalData(data, posX, posZ);
|
||||
boolean updated = this.dataContainer[detailLevel].addVerticalData(data, posX, posZ, override);
|
||||
if (updated) {
|
||||
needRegenBuffer = 2;
|
||||
needSaving = true;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,15 +158,6 @@ public class LodRegion {
|
||||
return dataContainer[detailLevel].getSingleData(posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the datapoint at the given relative position
|
||||
*/
|
||||
public void clear(byte detailLevel, int posX, int posZ) {
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
dataContainer[detailLevel].clear(posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will fill the posToGenerate array with all levelPos that are
|
||||
* render-able.
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.LongBuffer;
|
||||
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.dataFormat.*;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.util.*;
|
||||
@@ -92,10 +93,17 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addVerticalData(long[] data, int posX, int posZ)
|
||||
public boolean addVerticalData(long[] data, int posX, int posZ, boolean override)
|
||||
{
|
||||
int index = posX * size * verticalSize + posZ * verticalSize;
|
||||
int compare = DataPointUtil.compareDatapointPriority(data[0], dataContainer[index]);
|
||||
if (override) {
|
||||
if (compare<0) return false;
|
||||
} else {
|
||||
if (compare<=0) return false;
|
||||
}
|
||||
for (int verticalIndex = 0; verticalIndex < verticalSize; verticalIndex++)
|
||||
dataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex] = data[verticalIndex];
|
||||
dataContainer[index + verticalIndex] = data[verticalIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1131,7 +1139,7 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
}
|
||||
data = DataPointUtil.mergeMultiData(dataToMerge, lowerMaxVertical, getVerticalSize());
|
||||
|
||||
addVerticalData(data, posX, posZ);
|
||||
addVerticalData(data, posX, posZ, true);
|
||||
}
|
||||
|
||||
public void newUpdateData(VerticalLevelContainer lowerLevelContainer, int posX, int posZ)
|
||||
|
||||
@@ -267,6 +267,18 @@ public class DataPointUtil
|
||||
}
|
||||
}
|
||||
|
||||
/** Return (>0) if dataA should replace dataB, (0) if equal, (<0) if dataB should replace dataA */
|
||||
public static int compareDatapointPriority(long dataA, long dataB) {
|
||||
if (dataA==0 || dataB==0) {
|
||||
if (dataA!=0) dataA = Integer.MAX_VALUE;
|
||||
if (dataB!=0) dataB = Integer.MAX_VALUE;
|
||||
return (int)(dataA-dataB);
|
||||
}
|
||||
int genA = (int)getGenerationMode(dataA);
|
||||
int genB = (int)getGenerationMode(dataB);
|
||||
return genA-genB;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method merge column of multiple data together
|
||||
* @param dataToMerge one or more columns of data
|
||||
|
||||
@@ -44,7 +44,7 @@ public class DetailDistanceUtil
|
||||
private static int minDetailDistance = (int) (MC_RENDER.getRenderDistance()*16 * 1.42f);
|
||||
private static int maxDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * 16 * 2;
|
||||
|
||||
|
||||
@Deprecated
|
||||
private static final HorizontalResolution[] lodGenDetails = {
|
||||
HorizontalResolution.BLOCK,
|
||||
HorizontalResolution.TWO_BLOCKS,
|
||||
@@ -150,6 +150,7 @@ public class DetailDistanceUtil
|
||||
return detail;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static HorizontalResolution getLodGenDetail(int detail)
|
||||
{
|
||||
if (detail < minGenDetail)
|
||||
@@ -158,7 +159,8 @@ public class DetailDistanceUtil
|
||||
return lodGenDetails[detail];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Deprecated
|
||||
public static byte getCutLodDetail(int detail)
|
||||
{
|
||||
if (detail < minGenDetail)
|
||||
|
||||
Reference in New Issue
Block a user