This commit is contained in:
s809
2023-09-26 11:40:38 +05:00
11 changed files with 170 additions and 416 deletions
@@ -114,14 +114,18 @@ public class FullDataArrayAccessor implements IFullDataAccessor
{
for (int z = 0; z < this.width; z++)
{
long[] sourceData = this.dataArrays[this.offset + x * this.dataWidth + z];
long[] newData = new long[sourceData.length];
for (int dataPointIndex = 0; dataPointIndex < newData.length; dataPointIndex++)
long[] currentData = this.dataArrays[this.offset + x * this.dataWidth + z];
// may be null if no data exists for this column yet
if (currentData != null)
{
newData[dataPointIndex] = FullDataPointUtil.remap(remappedIds, sourceData[dataPointIndex]);
long[] newData = new long[currentData.length]; // TODO what to do if null?
for (int dataPointIndex = 0; dataPointIndex < newData.length; dataPointIndex++)
{
newData[dataPointIndex] = FullDataPointUtil.remap(remappedIds, currentData[dataPointIndex]);
}
target.dataArrays[target.offset + x * target.dataWidth + z] = newData;
}
target.dataArrays[target.offset + x * target.dataWidth + z] = newData;
}
}
}
@@ -28,8 +28,7 @@ import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStrea
import java.io.IOException;
import java.util.*;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
public abstract class AbstractFullDataSourceLoader
{
@@ -46,7 +45,7 @@ public abstract class AbstractFullDataSourceLoader
/** used when pooling data sources */
private final ArrayList<IFullDataSource> cachedSources = new ArrayList<>();
private final ReadWriteLock cacheReadWriteLock = new ReentrantReadWriteLock();
private final ReentrantLock cacheLock = new ReentrantLock();
@@ -159,7 +158,7 @@ public abstract class AbstractFullDataSourceLoader
{
try
{
this.cacheReadWriteLock.readLock().lock();
this.cacheLock.lock();
int index = this.cachedSources.size() - 1;
if (index == -1)
@@ -173,7 +172,7 @@ public abstract class AbstractFullDataSourceLoader
}
finally
{
this.cacheReadWriteLock.readLock().unlock();
this.cacheLock.unlock();
}
}
@@ -198,12 +197,12 @@ public abstract class AbstractFullDataSourceLoader
try
{
this.cacheReadWriteLock.writeLock().lock();
this.cacheLock.lock();
this.cachedSources.add(dataSource);
}
finally
{
this.cacheReadWriteLock.writeLock().unlock();
this.cacheLock.unlock();
}
}
@@ -297,6 +297,8 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
@Override
public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ) { return this.get(relativeX, relativeZ); }
@Override
public SingleColumnFullDataAccessor getOrCreate(int relativeX, int relativeZ) { return this.get(relativeX, relativeZ); }
@Override
public void update(ChunkSizedFullDataAccessor chunkDataView)
@@ -461,6 +463,7 @@ public class CompleteFullDataSource extends FullDataArrayAccessor implements IFu
@Override
public boolean isEmpty() { return this.isEmpty; }
@Override
public void markNotEmpty() { this.isEmpty = false; }
@Override
@@ -410,18 +410,31 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
// data //
//======//
public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ)
@Override
public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ) { return this.tryGetOrCreate(relativeX, relativeZ, false); }
@Override
public SingleColumnFullDataAccessor getOrCreate(int relativeX, int relativeZ) { return this.tryGetOrCreate(relativeX, relativeZ, true); }
private SingleColumnFullDataAccessor tryGetOrCreate(int relativeX, int relativeZ, boolean createIfMissing)
{
LodUtil.assertTrue(relativeX >= 0 && relativeX < SECTION_SIZE && relativeZ >= 0 && relativeZ < SECTION_SIZE);
int chunkX = relativeX / this.dataPointsPerSection;
int chunkZ = relativeZ / this.dataPointsPerSection;
FullDataArrayAccessor chunk = this.sparseData[chunkX * this.sectionCount + chunkZ];
if (chunk == null)
FullDataArrayAccessor accessor = this.sparseData[chunkX * this.sectionCount + chunkZ];
if (accessor == null)
{
return null;
if (createIfMissing)
{
// create the missing data so the following get() will succeed
accessor = new FullDataArrayAccessor(this.mapping, new long[this.dataPointsPerSection * this.dataPointsPerSection][], this.dataPointsPerSection);
this.sparseData[chunkX * this.sectionCount + chunkZ] = accessor;
}
else
{
return null;
}
}
return chunk.get(relativeX % this.dataPointsPerSection, relativeZ % this.dataPointsPerSection);
return accessor.get(relativeX % this.dataPointsPerSection, relativeZ % this.dataPointsPerSection);
}
@@ -470,6 +483,8 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
@Override
public boolean isEmpty() { return this.isEmpty; }
@Override
public void markNotEmpty() { this.isEmpty = false; }
@Override
public int getWidthInDataPoints() { return SECTION_SIZE; }
@@ -520,121 +535,6 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
// data sampling //
@Override
public void sampleFrom(IFullDataSource fullDataSource)
{
DhSectionPos pos = fullDataSource.getSectionPos();
LodUtil.assertTrue(pos.getDetailLevel() < this.sectionPos.getDetailLevel());
LodUtil.assertTrue(pos.overlapsExactly(this.sectionPos));
if (fullDataSource.isEmpty())
{
return;
}
if (fullDataSource instanceof CompleteFullDataSource)
{
this.sampleFrom((CompleteFullDataSource) fullDataSource);
}
else if (fullDataSource instanceof HighDetailIncompleteFullDataSource)
{
this.sampleFrom((HighDetailIncompleteFullDataSource) fullDataSource);
}
else if (fullDataSource instanceof LowDetailIncompleteFullDataSource)
{
// this.sampleFrom((LowDetailIncompleteFullDataSource) fullDataSource);
LodUtil.assertNotReach("SampleFrom not implemented for [" + IFullDataSource.class.getSimpleName() + "] with class [" + fullDataSource.getClass().getSimpleName() + "].");
}
else
{
LodUtil.assertNotReach("SampleFrom not implemented for [" + IFullDataSource.class.getSimpleName() + "] with class [" + fullDataSource.getClass().getSimpleName() + "].");
}
}
private void sampleFrom(CompleteFullDataSource completeDataSource)
{
DhSectionPos pos = completeDataSource.getSectionPos();
this.isEmpty = false;
DhLodPos basePos = this.sectionPos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
DhLodPos dataPos = pos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
int coveredChunks = pos.getWidthCountForLowerDetailedSection(SPARSE_UNIT_DETAIL);
int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> completeDataSource.getDataDetailLevel();
LodUtil.assertTrue((coveredChunks * sourceDataPerChunk) == CompleteFullDataSource.WIDTH);
int xDataOffset = dataPos.x - basePos.x;
int zDataOffset = dataPos.z - basePos.z;
LodUtil.assertTrue(xDataOffset >= 0 && xDataOffset < this.sectionCount && zDataOffset >= 0 && zDataOffset < this.sectionCount);
for (int xOffset = 0; xOffset < coveredChunks; xOffset++)
{
for (int zOffset = 0; zOffset < coveredChunks; zOffset++)
{
FullDataArrayAccessor sourceChunk = completeDataSource.subView(sourceDataPerChunk, xOffset * sourceDataPerChunk, zOffset * sourceDataPerChunk);
FullDataArrayAccessor newFullDataAccessor = new FullDataArrayAccessor(this.mapping, new long[this.dataPointsPerSection * this.dataPointsPerSection][], this.dataPointsPerSection);
newFullDataAccessor.downsampleFrom(sourceChunk);
this.sparseData[(xOffset + xDataOffset) * this.sectionCount + (zOffset + zDataOffset)] = newFullDataAccessor;
}
}
}
private void sampleFrom(HighDetailIncompleteFullDataSource sparseDataSource)
{
DhSectionPos pos = sparseDataSource.getSectionPos();
this.isEmpty = false;
DhLodPos basePos = this.sectionPos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
DhLodPos dataPos = pos.getMinCornerLodPos(SPARSE_UNIT_DETAIL);
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < this.sectionCount && offsetZ >= 0 && offsetZ < this.sectionCount);
for (int xOffset = 0; xOffset < sparseDataSource.sectionCount; xOffset++)
{
for (int zOffset = 0; zOffset < sparseDataSource.sectionCount; zOffset++)
{
FullDataArrayAccessor sourceChunk = sparseDataSource.sparseData[xOffset * sparseDataSource.sectionCount + zOffset];
if (sourceChunk != null)
{
FullDataArrayAccessor newFullDataAccessor = new FullDataArrayAccessor(this.mapping, new long[this.dataPointsPerSection * this.dataPointsPerSection][], this.dataPointsPerSection);
newFullDataAccessor.downsampleFrom(sourceChunk);
this.sparseData[(xOffset + offsetX) * this.sectionCount + (zOffset + offsetZ)] = newFullDataAccessor;
}
}
}
}
private void sampleFrom(LowDetailIncompleteFullDataSource spottyDataSource)
{
// TODO implement
// DhSectionPos pos = spottyDataSource.getSectionPos();
// this.isEmpty = false;
//
// DhLodPos basePos = this.sectionPos.getCorner(SPARSE_UNIT_DETAIL);
// DhLodPos dataPos = pos.getCorner(SPARSE_UNIT_DETAIL);
//
// int coveredChunks = pos.getWidth(SPARSE_UNIT_DETAIL).numberOfLodSectionsWide;
// int sourceDataPerChunk = SPARSE_UNIT_SIZE >>> spottyDataSource.getDataDetailLevel();
// LodUtil.assertTrue((coveredChunks * sourceDataPerChunk) == CompleteFullDataSource.WIDTH);
//
// int xDataOffset = dataPos.x - basePos.x;
// int zDataOffset = dataPos.z - basePos.z;
// LodUtil.assertTrue(xDataOffset >= 0 && xDataOffset < this.sectionCount && zDataOffset >= 0 && zDataOffset < this.sectionCount);
//
// for (int xOffset = 0; xOffset < coveredChunks; xOffset++)
// {
// for (int zOffset = 0; zOffset < coveredChunks; zOffset++)
// {
// FullDataArrayAccessor sourceChunk = spottyDataSource.subView(sourceDataPerChunk, xOffset * sourceDataPerChunk, zOffset * sourceDataPerChunk);
// FullDataArrayAccessor newFullDataAccessor = new FullDataArrayAccessor(this.mapping, new long[this.dataPointsPerSection * this.dataPointsPerSection][], this.dataPointsPerSection);
// newFullDataAccessor.downsampleFrom(sourceChunk);
// this.sparseData[(xOffset + xDataOffset) * this.sectionCount + (zOffset + zDataOffset)] = newFullDataAccessor;
// }
// }
}
private void applyToFullDataSource(CompleteFullDataSource dataSource)
{
LodUtil.assertTrue(dataSource.getSectionPos().equals(this.sectionPos));
@@ -670,16 +570,13 @@ public class HighDetailIncompleteFullDataSource implements IIncompleteFullDataSo
return this;
}
}
isPromoted = true;
this.isPromoted = true;
CompleteFullDataSource fullDataSource = CompleteFullDataSource.createEmpty(this.sectionPos);
this.applyToFullDataSource(fullDataSource);
return fullDataSource;
}
@Override
public boolean hasBeenPromoted()
{
return isPromoted;
}
public boolean hasBeenPromoted() { return this.isPromoted; }
}
@@ -284,7 +284,23 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
//======//
@Override
public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ) { return this.isColumnNotEmpty.get(relativeX * WIDTH + relativeZ) ? this.get(relativeX, relativeZ) : null; }
public SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ) { return this.tryGetOrCreate(relativeX, relativeZ, false); }
@Override
public SingleColumnFullDataAccessor getOrCreate(int relativeX, int relativeZ) { return this.tryGetOrCreate(relativeX, relativeZ, true); }
private SingleColumnFullDataAccessor tryGetOrCreate(int relativeX, int relativeZ, boolean createIfMissing)
{
int notEmptyIndex = relativeX * WIDTH + relativeZ;
boolean columnEmpty = this.isColumnNotEmpty.get(notEmptyIndex);
// "create" the missing column if necessary
if (columnEmpty && createIfMissing)
{
this.isColumnNotEmpty.set(notEmptyIndex, true);
columnEmpty = false;
}
return !columnEmpty ? this.get(relativeX, relativeZ) : null;
}
@@ -314,6 +330,7 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
@Override
public boolean isEmpty() { return this.isEmpty; }
@Override
public void markNotEmpty() { this.isEmpty = false; }
@Override
@@ -359,170 +376,6 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
}
@Override
public void sampleFrom(IFullDataSource fullDataSource)
{
DhSectionPos pos = fullDataSource.getSectionPos();
LodUtil.assertTrue(pos.getDetailLevel() < this.sectionPos.getDetailLevel());
LodUtil.assertTrue(pos.overlapsExactly(this.sectionPos));
if (fullDataSource.isEmpty())
{
return;
}
if (fullDataSource instanceof CompleteFullDataSource)
{
this.sampleFrom((CompleteFullDataSource) fullDataSource);
}
else if (fullDataSource instanceof HighDetailIncompleteFullDataSource)
{
this.sampleFrom((HighDetailIncompleteFullDataSource) fullDataSource);
}
else if (fullDataSource instanceof LowDetailIncompleteFullDataSource)
{
this.sampleFrom((LowDetailIncompleteFullDataSource) fullDataSource);
// LodUtil.assertNotReach("SampleFrom not implemented for ["+IFullDataSource.class.getSimpleName()+"] with class ["+fullDataSource.getClass().getSimpleName()+"].");
}
else
{
// TODO implement
LodUtil.assertNotReach("SampleFrom not implemented for [" + this.getClass().getSimpleName() + "] with class [" + fullDataSource.getClass().getSimpleName() + "].");
}
}
private void sampleFrom(HighDetailIncompleteFullDataSource sparseSource)
{
DhLodPos thisLodPos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhSectionPos pos = sparseSource.getSectionPos();
this.isEmpty = false;
if (this.getDataDetailLevel() > this.sectionPos.getDetailLevel())
{
DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
int offsetX = dataLodPos.x - thisLodPos.x;
int offsetZ = dataLodPos.z - thisLodPos.z;
LodUtil.assertTrue(offsetX >= 0 && offsetX < WIDTH && offsetZ >= 0 && offsetZ < WIDTH);
int chunksPerData = 1 << (this.getDataDetailLevel() - HighDetailIncompleteFullDataSource.SPARSE_UNIT_DETAIL);
int dataSpan = this.sectionPos.getWidthCountForLowerDetailedSection(this.getDataDetailLevel());
for (int xOffset = 0; xOffset < dataSpan; xOffset++)
{
for (int zOffset = 0; zOffset < dataSpan; zOffset++)
{
SingleColumnFullDataAccessor column = sparseSource.tryGet(
xOffset * chunksPerData * sparseSource.dataPointsPerSection,
zOffset * chunksPerData * sparseSource.dataPointsPerSection);
if (column != null)
{
column.deepCopyTo(this.get(offsetX + xOffset, offsetZ + zOffset));
this.isColumnNotEmpty.set((offsetX + xOffset) * WIDTH + offsetZ + zOffset, true);
}
}
}
}
else
{
DhLodPos dataLodPos = pos.getSectionBBoxPos();
int lowerSectionsPerData = this.sectionPos.getWidthCountForLowerDetailedSection(dataLodPos.detailLevel);
if (dataLodPos.x % lowerSectionsPerData != 0 || dataLodPos.z % lowerSectionsPerData != 0)
{
return;
}
dataLodPos = dataLodPos.convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataLodPos.x - thisLodPos.x;
int offsetZ = dataLodPos.z - thisLodPos.z;
SingleColumnFullDataAccessor column = sparseSource.tryGet(0, 0);
if (column != null)
{
column.deepCopyTo(this.get(offsetX, offsetZ));
this.isColumnNotEmpty.set(offsetX * WIDTH + offsetZ, true);
}
}
}
private void sampleFrom(CompleteFullDataSource inputSource)
{
DhSectionPos inputPos = inputSource.getSectionPos();
this.isEmpty = false;
DhLodPos baseOffset = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhSectionPos inputOffset = inputPos.convertNewToDetailLevel(this.getDataDetailLevel());
int offsetX = inputOffset.getX() - baseOffset.x;
int offsetZ = inputOffset.getZ() - baseOffset.z;
int numberOfDataPointsToUpdate = WIDTH / this.sectionPos.getWidthCountForLowerDetailedSection(inputSource.getSectionPos().getDetailLevel()); // can be 0 if the input source is significantly smaller than this data source
// should be 1 at minimum, to prevent divide by zero errors (and because trying to get 0 data points doesn't make any sense)
numberOfDataPointsToUpdate = Math.max(1, numberOfDataPointsToUpdate);
int inputFractionWidth = inputSource.width() / numberOfDataPointsToUpdate;
for (int x = 0; x < numberOfDataPointsToUpdate; x++)
{
for (int z = 0; z < numberOfDataPointsToUpdate; z++)
{
SingleColumnFullDataAccessor thisDataColumn = this.get(offsetX + x, offsetZ + z);
SingleColumnFullDataAccessor inputDataColumn = inputSource.get(inputFractionWidth * x, inputFractionWidth * z);
inputDataColumn.deepCopyTo(thisDataColumn);
int notEmptyIndex = (offsetX + x) * WIDTH + (offsetZ + z);
this.isColumnNotEmpty.set(notEmptyIndex, true);
}
}
}
private void sampleFrom(LowDetailIncompleteFullDataSource spottySource)
{
DhSectionPos pos = spottySource.getSectionPos();
this.isEmpty = false;
this.downsampleFrom(spottySource);
if (this.getDataDetailLevel() > this.sectionPos.getDetailLevel())
{
DhLodPos thisLodPos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
DhLodPos dataLodPos = pos.getMinCornerLodPos(this.getDataDetailLevel());
int offsetX = dataLodPos.x - thisLodPos.x;
int offsetZ = dataLodPos.z - thisLodPos.z;
int dataWidth = this.sectionPos.getWidthCountForLowerDetailedSection(this.getDataDetailLevel());
for (int xOffset = 0; xOffset < dataWidth; xOffset++)
{
for (int zOffset = 0; zOffset < dataWidth; zOffset++)
{
this.isColumnNotEmpty.set((offsetX + xOffset) * WIDTH + offsetZ + zOffset, true);
}
}
}
else
{
DhLodPos dataPos = pos.getSectionBBoxPos();
int lowerSectionsPerData = this.sectionPos.getWidthCountForLowerDetailedSection(dataPos.detailLevel);
if (dataPos.x % lowerSectionsPerData != 0 || dataPos.z % lowerSectionsPerData != 0)
{
return;
}
DhLodPos basePos = this.sectionPos.getMinCornerLodPos(this.getDataDetailLevel());
dataPos = dataPos.convertToDetailLevel(this.getDataDetailLevel());
int offsetX = dataPos.x - basePos.x;
int offsetZ = dataPos.z - basePos.z;
this.isColumnNotEmpty.set(offsetX * WIDTH + offsetZ, true);
}
}
@Override
public IFullDataSource tryPromotingToCompleteDataSource()
{
@@ -535,15 +388,13 @@ public class LowDetailIncompleteFullDataSource extends FullDataArrayAccessor imp
{
return this;
}
isPromoted = true;
this.isPromoted = true;
return new CompleteFullDataSource(this.sectionPos, this.mapping, this.dataArrays);
}
@Override
public boolean hasBeenPromoted()
{
return isPromoted;
}
public boolean hasBeenPromoted() { return this.isPromoted; }
//================//
@@ -69,6 +69,7 @@ public interface IFullDataSource
void update(ChunkSizedFullDataAccessor data);
boolean isEmpty();
void markNotEmpty();
/** AKA; the max relative position that {@link IFullDataSource#tryGet(int, int)} can accept for either X or Z */
int getWidthInDataPoints();
@@ -85,6 +86,11 @@ public interface IFullDataSource
* @return null if the data doesn't exist
*/
SingleColumnFullDataAccessor tryGet(int relativeX, int relativeZ);
/**
* Attempts to get the data column for the given relative x and z position. <br>
* If no data exists yet an empty data column will be created.
*/
SingleColumnFullDataAccessor getOrCreate(int relativeX, int relativeZ);
FullDataPointIdMap getMapping();
@@ -19,7 +19,11 @@
package com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces;
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.SingleColumnFullDataAccessor;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource;
import com.seibel.distanthorizons.core.pos.DhLodPos;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.util.LodUtil;
public interface IIncompleteFullDataSource extends IFullDataSource
{
@@ -28,7 +32,47 @@ public interface IIncompleteFullDataSource extends IFullDataSource
*
* This can be used to either merge same sized data sources or downsample to
*/
void sampleFrom(IFullDataSource fullDataSource);
default void sampleFrom(IFullDataSource inputSource)
{
DhSectionPos inputPos = inputSource.getSectionPos();
DhSectionPos thisPos = this.getSectionPos();
LodUtil.assertTrue(inputPos.getDetailLevel() < thisPos.getDetailLevel());
LodUtil.assertTrue(inputPos.overlapsExactly(this.getSectionPos()));
if (inputSource.isEmpty())
{
return;
}
this.markNotEmpty();
DhLodPos baseOffset = thisPos.getMinCornerLodPos(this.getDataDetailLevel());
DhSectionPos inputOffset = inputPos.convertNewToDetailLevel(this.getDataDetailLevel());
int offsetX = inputOffset.getX() - baseOffset.x;
int offsetZ = inputOffset.getZ() - baseOffset.z;
int numberOfDataPointsToUpdate = this.getWidthInDataPoints() / thisPos.getWidthCountForLowerDetailedSection(inputSource.getSectionPos().getDetailLevel()); // can be 0 if the input source is significantly smaller than this data source
// should be 1 at minimum, to prevent divide by zero errors (and because trying to get 0 or a fractional data point doesn't make any sense)
numberOfDataPointsToUpdate = Math.max(1, numberOfDataPointsToUpdate);
int inputFractionWidth = inputSource.getWidthInDataPoints() / numberOfDataPointsToUpdate;
for (int x = 0; x < numberOfDataPointsToUpdate; x++)
{
for (int z = 0; z < numberOfDataPointsToUpdate; z++)
{
SingleColumnFullDataAccessor thisDataColumn = this.getOrCreate(offsetX + x, offsetZ + z);
SingleColumnFullDataAccessor inputDataColumn = inputSource.tryGet(inputFractionWidth * x, inputFractionWidth * z);
if (inputDataColumn != null)
{
inputDataColumn.deepCopyTo(thisDataColumn);
}
}
}
}
/**
* Attempts to convert this {@link IIncompleteFullDataSource} into a {@link CompleteFullDataSource}.
@@ -386,7 +386,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
FullDataMetaFile existingFile = existingFiles.get(i);
CompletableFuture<IFullDataSource> loadFileFuture = usePooledDataSources ? existingFile.getOrLoadCachedDataSourceAsync() : existingFile.getDataSourceWithoutCachingAsync();
CompletableFuture<IFullDataSource> loadFileFuture = usePooledDataSources ? existingFile.getDataSourceWithoutCachingAsync() : existingFile.getOrLoadCachedDataSourceAsync();
CompletableFuture<IFullDataSource> sampleSourceFuture = loadFileFuture.whenComplete((existingFullDataSource, ex) ->
{
@@ -415,7 +415,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider
}
// pooling temporary data sources massively reduces garbage collector overhead when just sampling (going from ~8 GB/sec to ~90 MB/sec)
if (!usePooledDataSources && !existingFile.cacheLoadingDataSource)
if (usePooledDataSources && !existingFile.cacheLoadingDataSource)
{
existingFile.clearCachedDataSource();
@@ -277,7 +277,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements AutoClose
{
// this is the detail level we want to render //
// prepare this section for rendering
renderSection.loadRenderSource(this.renderSourceProvider, this.level);
renderSection.loadRenderSource(this.renderSourceProvider, this.level); // TODO this should fire for the lowest detail level first, wait for it to finish then fire the next highest to prevent waiting forever for 2 million chunk section to finish sampling everything
// wait for the parent to disable before enabling this section, so we don't overdraw/overlap render sections
if (!parentRenderSectionIsEnabled && renderSection.canRenderNow())
@@ -333,7 +333,7 @@
"distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode":
"Server Folder Mode",
"distanthorizons.config.client.multiplayer.serverFolderNameMode.@tooltip":
"distanthorizons.config.client.advanced.multiplayer.serverFolderNameMode.@tooltip":
"Determines the folder format for local multiplayer data.\n\n§6Name Only:§r\nUses the server browser name. Ex: \"Minecraft Server\"\n§6Name IP:§r\n\"Minecraft Server, IP 192.168.1.40\"\n§6Name, IP, Port:§r\n\"Minecraft Server, IP 192.168.1.40:25565\"\n§6Name, IP, Port, MC Version:§r\n\"Minecraft Server, IP 192.168.1.40:25565, GameVersion 1.18.1\"\n\n§c§lCaution:§r changing while connected to a multiplayer server may cause glitches.",
"distanthorizons.config.client.advanced.multiplayer.multiverseSimilarityRequiredPercent":
"Multiverse Required Similarity %",
@@ -1,94 +1,62 @@
{
"distanthorizons.title":
"Distant Horizons",
"Distant Horizons",
"distanthorizons.general.true":
"Вкл.",
"distanthorizons.general.false":
"Выкл.",
"distanthorizons.general.yes":
"Да",
"distanthorizons.general.no":
"Нет",
"distanthorizons.general.back":
"Назад",
"distanthorizons.general.next":
"Следующий",
"distanthorizons.general.done":
"Готово",
"distanthorizons.general.cancel":
"Отмена",
"distanthorizons.general.reset":
"Сброc",
"distanthorizons.general.true": "Вкл.",
"distanthorizons.general.false": "Выкл.",
"distanthorizons.general.reset": "Сброc",
"distanthorizons.general.back": "Назад",
"distanthorizons.general.next": "Следующий",
"distanthorizons.general.done": "Готово",
"distanthorizons.general.cancel": "Отмена",
"distanthorizons.general.yes": "Да",
"distanthorizons.general.no": "Нет",
"distanthorizons.updater.title":
"Автоматическое обновление Distant Horizons",
"distanthorizons.updater.text1":
"§lДоступно новое обновление!",
"distanthorizons.updater.text2":
"§fВы хотите перейти с %s§f на %s§f?",
"distanthorizons.updater.later":
"Не сейчас",
"distanthorizons.updater.never":
"Не показывать снова",
"distanthorizons.updater.update":
"Обновить",
"distanthorizons.updater.update.@tooltip":
"Обновить мод 1 раз\n(обновляется при закрытии игры)",
"distanthorizons.updater.silent":
"Всегда тихое обновление",
"distanthorizons.updater.silent.@tooltip":
"Каждый раз, когда доступно обновление, оно будет обновляться\n(§6ПРЕДУПРЕЖДЕНИЕ§r: Оно не будет запрашивать у пользователя разрешение на обновление, но будет поддерживать мод в актуальном состоянии)",
"distanthorizons.updater.waitingForClose":
"Обновление Distant Horizons завершится после перезапуска игры",
"distanthorizons.updater.title": "Автоматическое обновление Distant Horizons",
"distanthorizons.updater.text1": "§lДоступно новое обновление!",
"distanthorizons.updater.text2": "§fВы хотите перейти с %s§f на %s§f?",
"distanthorizons.updater.later": "Не сейчас",
"distanthorizons.updater.never": "Не показывать снова",
"distanthorizons.updater.update": "Обновить",
"distanthorizons.updater.update.@tooltip": "Обновить мод 1 раз\n(обновляется при закрытии игры)",
"distanthorizons.updater.silent": "Всегда тихое обновление",
"distanthorizons.updater.silent.@tooltip": "Каждый раз, когда доступно обновление, оно будет обновляться\n(§6ПРЕДУПРЕЖДЕНИЕ§r: Оно не будет запрашивать у пользователя разрешение на обновление, но будет поддерживать мод в актуальном состоянии)",
"distanthorizons.updater.waitingForClose": "Обновление Distant Horizons завершится после перезапуска игры",
"distanthorizons.config.title":
"Конфигурация Distant Horizons",
"distanthorizons.config.client":
"Клиент",
"distanthorizons.config.title": "Конфигурация Distant Horizons",
"distanthorizons.config.client.quickEnableRendering":
"Включить рендеринг",
"distanthorizons.config.client.quickEnableRendering.@tooltip":
"Определяет, отображает ли Distant Horizons LODs.",
"distanthorizons.config.client.qualityPresetSetting":
"Предустановленное качество",
"distanthorizons.config.client.qualityPresetSetting.@tooltip":
"Изменяет ряд графических настроек для быстрого изменения качества рендеринга Distant Horizons. \n\nУменьшите этот параметр, если ваш графический процессор максимально загружен или у вас возникли проблемы с частотой кадров.",
"distanthorizons.config.client.threadPresetSetting":
"Загруженность процессора",
"distanthorizons.config.client.threadPresetSetting.@tooltip":
"Изменяет количество потоков, которые будут использоваться в Distant Horizons. \n\nУвеличение этого параметра улучшит скорость удаленного генератора (Distant Generator) и скорость загрузки LOD, \nно также увеличит использование процессора/памяти и может привести к заиканию. \n\nПримечание: на процессорах с 4 ядрами или меньше эти настройки будут менее эффективными, \nи некоторые настройки дадут аналогичные результаты.",
"distanthorizons.config.client.optionsButton":
"Отобразить кнопку Параметров",
"distanthorizons.config.client.optionsButton.@tooltip":
"Показать кнопку Параметров слева от кнопки FOV.",
"distanthorizons.config.client": "Клиент",
"distanthorizons.config.client.quickEnableRendering": "Включить рендеринг",
"distanthorizons.config.client.quickEnableRendering.@tooltip": "Определяет, отображает ли Distant Horizons LODs.",
"distanthorizons.config.client.qualityPresetSetting": "Предустановленное качество",
"distanthorizons.config.client.qualityPresetSetting.@tooltip": "Изменяет ряд графических настроек для быстрого изменения качества рендеринга Distant Horizons. \n\nУменьшите этот параметр, если ваш графический процессор максимально загружен или у вас возникли проблемы с частотой кадров.",
"distanthorizons.config.client.threadPresetSetting": "Загруженность процессора",
"distanthorizons.config.client.threadPresetSetting.@tooltip": "Изменяет количество потоков, которые будут использоваться в Distant Horizons. \n\nУвеличение этого параметра улучшит скорость удаленного генератора (Distant Generator) и скорость загрузки LOD, \nно также увеличит использование процессора/памяти и может привести к заиканию. \n\nПримечание: на процессорах с 4 ядрами или меньше эти настройки будут менее эффективными, \nи некоторые настройки дадут аналогичные результаты.",
"distanthorizons.config.client.optionsButton": "Отобразить кнопку Параметров",
"distanthorizons.config.client.optionsButton.@tooltip": "Показать кнопку Параметров слева от кнопки FOV.",
"distanthorizons.config.client.advanced":
"Расширенные параметры",
"distanthorizons.config.client.advanced": "Расширенные параметры",
"distanthorizons.config.client.advanced.graphics":
"Графика",
"distanthorizons.config.client.advanced.graphics.quality":
"Качество рендеринга",
"distanthorizons.config.client.advanced.graphics": "Графика",
"distanthorizons.config.client.advanced.graphics.quality": "Качество рендеринга",
"distanthorizons.config.client.advanced.graphics.quality.maxHorizontalResolution": "Максимальное горизонтальное разрешение",
"distanthorizons.config.client.advanced.graphics.quality.maxHorizontalResolution.@tooltip": "Изображения с максимальной детализацией отображаются на.\n\n§6Самый быстрый:§r Чанк\n§6Самый красивый:§r Блок",
"distanthorizons.config.client.advanced.graphics.quality.lodChunkRenderDistance": "Расстояние рендеринга LOD",
"distanthorizons.config.client.advanced.graphics.quality.lodChunkRenderDistance.@tooltip": "Расстояние рендеринга Distant Horizons, измеряемое в чанках. \n\nПримечание: это максимально возможное число. \nДальность рендеринга может быть выше или ниже этого числа \nв зависимости от других графических настроек.",
"distanthorizons.config.client.advanced.graphics.quality.verticalQuality": "Вертикальное качество",
"distanthorizons.config.client.advanced.graphics.quality.verticalQuality.@tooltip": "На сколько хорошо LOD (уровень детализации) отображает выступы, пещеры, обрывы и т.д.\n\nБолее высокие параметры будут увеличивать использование памяти и GPU.",
"distanthorizons.config.client.advanced.graphics.quality.verticalQuality.@tooltip": "На сколько хорошо LOD отображает выступы, пещеры, обрывы и т.д.\n\nБолее высокие параметры будут увеличивать использование памяти и GPU.",
"distanthorizons.config.client.advanced.graphics.quality.horizontalScale": "Горизонтальная шкала",
"distanthorizons.config.client.advanced.graphics.quality.horizontalScale.@tooltip": "На сколько быстро уровни детализации (LOD) снижают качество.\n\nБольшие значения улучшат вид дальней местности, \nно увеличат использование памяти и GPU.",
"distanthorizons.config.client.advanced.graphics.quality.horizontalQuality": "Горизонтальное качество",
@@ -105,11 +73,11 @@
"distanthorizons.config.client.advanced.graphics.fog": "Туман",
"distanthorizons.config.client.advanced.graphics.fog.drawMode": "Режим отображения тумана",
"distanthorizons.config.client.advanced.graphics.fog.drawMode.@tooltip": "Когда будет отрисовываться туман на LODs (уровнях детализации).",
"distanthorizons.config.client.advanced.graphics.fog.drawMode.@tooltip": "Когда будет отрисовываться туман на LOD-ах (уровнях детализации).",
"distanthorizons.config.client.advanced.graphics.fog.distance": "Дальность тумана",
"distanthorizons.config.client.advanced.graphics.fog.distance.@tooltip": "Дальность(и), на которой туман будет отрисовываться на LODs.",
"distanthorizons.config.client.advanced.graphics.fog.distance.@tooltip": "Дальность(и), на которой туман будет отрисовываться на LOD-ах.",
"distanthorizons.config.client.advanced.graphics.fog.colorMode": "Режим цвета тумана",
"distanthorizons.config.client.advanced.graphics.fog.colorMode.@tooltip": "Цвет тумана на LODs.",
"distanthorizons.config.client.advanced.graphics.fog.colorMode.@tooltip": "Цвет тумана на LOD-ах.",
"distanthorizons.config.client.advanced.graphics.fog.disableVanillaFog": "Отключить ванильный туман",
"distanthorizons.config.client.advanced.graphics.fog.disableVanillaFog.@tooltip": "§6Вкл.:§r отключает туман Minecraft на ванильных чанках. \n§6Выкл.:§r Minecraft отрисовывает туман как обычно. \n\nМожет вызывать проблемы с другими модами, изменяющими туман. \nОтключите, если ванильные чанки полностью покрыты туманом.",
"distanthorizons.config.client.advanced.graphics.fog.advancedFog": "Дополнительные настройки тумана",
@@ -127,12 +95,12 @@
"distanthorizons.config.client.advanced.graphics.fog.advancedFog.farFogDensity.@tooltip": "Какая должна быть плотность дальнего тумана? ",
"distanthorizons.config.client.advanced.graphics.ssao": "Окружающая окклюзия (Ambient Occlusion)",
"distanthorizons.config.client.advanced.graphics.ssao": "Окружающая окклюзия",
"distanthorizons.config.client.advanced.graphics.ssao.enabled": "Включить окружающую окклюзию (Ambient Occlusion)",
"distanthorizons.config.client.advanced.graphics.ssao.enabled.@tooltip": "Окружающая окклюзия добавляет глубину к освещению блоков.",
"distanthorizons.config.client.advanced.graphics.ssao.sampleCount": "Количество образцов",
"distanthorizons.config.client.advanced.graphics.ssao.sampleCount.@tooltip": "Определяет, сколько точек в пространстве отбирается для теста окклюзии. \nБольшее количество улучшит качество и уменьшит полосирование, но увеличит нагрузку на ГПУ.",
"distanthorizons.config.client.advanced.graphics.ssao.sampleCount.@tooltip": "Определяет, сколько точек в пространстве отбирается для теста окклюзии. \nБольшее количество улучшит качество и уменьшит полосирование, но увеличит нагрузку на графический процессор.",
"distanthorizons.config.client.advanced.graphics.ssao.radius": "Радиус",
"distanthorizons.config.client.advanced.graphics.ssao.radius.@tooltip": "Определяет радиус применения эффекта окружающей окклюзии в блоках.",
"distanthorizons.config.client.advanced.graphics.ssao.strength": "Сила",
@@ -232,25 +200,20 @@
"distanthorizons.config.client.advanced.multiThreading.numberOfWorldGenerationThreads": "Количество потоков генерации мира",
"distanthorizons.config.client.advanced.multiThreading.numberOfWorldGenerationThreads.@tooltip": "Сколько потоков следует использовать при генерации LODs вне обычной зоны отрисовки? \n\nЕсли это число меньше 1, оно будет рассматриваться как процент времени, в течение которого один поток может работать, прежде чем перейти в режим ожидания. \n\nЕсли у вас есть проблемы с прерываниями при генерации дальних LODs, уменьшите это число. Если вы хотите увеличить скорость генерации LOD, увеличьте это число. \n\nКоличество потоков для генерации LOD и количество потоков для построения буферов независимы друг от друга. Если их сумма больше количества ядер вашего процессора, это нормально.",
"distanthorizons.config.client.advanced.multiThreading.runTimeRatioForWorldGenerationThreads": "Процент времени выполнения для потоков генерации мира",
"distanthorizons.config.client.advanced.multiThreading.numberOfBufferBuilderThreads": "Количество потоков построения буферов",
"distanthorizons.config.client.advanced.multiThreading.numberOfBufferBuilderThreads.@tooltip": "Количество потоков, используемых при построении данных геометрии. \nМожет быть только от 1 до количества процессорных ядер вашего CPU.",
"distanthorizons.config.client.advanced.multiThreading.runTimeRatioForBufferBuilderThreads": "Процент времени выполнения для потоков построения буферов",
"distanthorizons.config.client.advanced.multiThreading.numberOfFileHandlerThreads": "Количество потоков обработки файлов",
"distanthorizons.config.client.advanced.multiThreading.numberOfFileHandlerThreads.@tooltip": "Количество потоков, используемых при построении буферов вершин (вещей, отправляемых на ваш GPU для отрисовки LODs). \nМожет быть только от 1 до количества процессорных ядер вашего CPU.",
"distanthorizons.config.client.advanced.multiThreading.runTimeRatioForFileHandlerThreads": "Процент времени выполнения для потоков обработки файлов",
"distanthorizons.config.client.advanced.multiThreading.numberOfDataTransformerThreads": "Количество потоков преобразования данных",
"distanthorizons.config.client.advanced.multiThreading.numberOfDataTransformerThreads.@tooltip": "Количество потоков, используемых при преобразовании данных ID в данные, подходящие для отрисовки. \n(Это, как правило, происходит при генерации нового ландшафта или изменении настроек графики). \nМожет быть только от 1 до количества процессорных ядер вашего CPU.",
"distanthorizons.config.client.advanced.multiThreading.runTimeRatioForDataTransformerThreads": "Процент времени выполнения для потоков преобразования данных",
"distanthorizons.config.client.advanced.multiThreading.numberOfChunkLodConverterThreads": "Количество потоков преобразования LOD чанков",
"distanthorizons.config.client.advanced.multiThreading.numberOfChunkLodConverterThreads.@tooltip": "Сколько потоков следует использовать для преобразования чанков Minecraft в данные LOD? \nЭти потоки работают как при генерации мира, так и при загрузке, выгрузке и модификации чанков.",
"distanthorizons.config.client.advanced.multiThreading.runTimeRatioForChunkLodConverterThreads": "Процент времени выполнения для потоков преобразования LOD чанков",
"distanthorizons.config.client.advanced.debugging": "Отладка",
"distanthorizons.config.client.advanced.debugging.rendererMode": "Режим рендера",
"distanthorizons.config.client.advanced.debugging.debugRendering": "Отладка рендера",
@@ -331,7 +294,6 @@
"distanthorizons.config.client.advanced.debugging.debugWireframe.showRenderDataFileStatus": "Показать статус файла данных отрисовки",
"distanthorizons.config.client.resetSettingsConfirmation": "Сбросить все настройки?",
"distanthorizons.config.client.resetSettingsConfirmation.resetConfirmationNote": "Вы уверены? Это действие нельзя отменить!",
"distanthorizons.config.client.resetSettingsConfirmation.resetAllSettings": "Сбросить все настройки",
@@ -470,31 +432,19 @@
"distanthorizons.config.enum.ELoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE": "Файл: Информация, Чат: Предупреждения",
"distanthorizons.config.enum.ELoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE": "Файл: Информация, Чат: Ошибки",
"distanthorizons.config.enum.EGpuUploadMethod.AUTO":
"Авто",
"distanthorizons.config.enum.EGpuUploadMethod.BUFFER_STORAGE":
"Хранение буфера",
"distanthorizons.config.enum.EGpuUploadMethod.SUB_DATA":
"Данные SUB",
"distanthorizons.config.enum.EGpuUploadMethod.BUFFER_MAPPING":
"Отображение буфера",
"distanthorizons.config.enum.EGpuUploadMethod.DATA":
"Данные",
"distanthorizons.config.enum.EGpuUploadMethod.AUTO": "Авто",
"distanthorizons.config.enum.EGpuUploadMethod.BUFFER_STORAGE": "Хранение буфера",
"distanthorizons.config.enum.EGpuUploadMethod.SUB_DATA": "Данные SUB",
"distanthorizons.config.enum.EGpuUploadMethod.BUFFER_MAPPING": "Отображение буфера",
"distanthorizons.config.enum.EGpuUploadMethod.DATA": "Данные",
"distanthorizons.config.enum.EBufferRebuildTimes.CONSTANT":
"Постоянно",
"distanthorizons.config.enum.EBufferRebuildTimes.FREQUENT":
"Часто",
"distanthorizons.config.enum.EBufferRebuildTimes.NORMAL":
"Обычно",
"distanthorizons.config.enum.EBufferRebuildTimes.RARE":
"Редко",
"distanthorizons.config.enum.EBufferRebuildTimes.CONSTANT": "Постоянно",
"distanthorizons.config.enum.EBufferRebuildTimes.FREQUENT": "Часто",
"distanthorizons.config.enum.EBufferRebuildTimes.NORMAL": "Обычно",
"distanthorizons.config.enum.EBufferRebuildTimes.RARE": "Редко",
"distanthorizons.config.enum.ELodShading.MINECRAFT":
"Майнкрафт-овское",
"distanthorizons.config.enum.ELodShading.OLD_LIGHTING":
"Старое освещение",
"distanthorizons.config.enum.ELodShading.NONE":
"Ничего"
"distanthorizons.config.enum.ELodShading.MINECRAFT": "Майнкрафт-овское",
"distanthorizons.config.enum.ELodShading.OLD_LIGHTING": "Старое освещение",
"distanthorizons.config.enum.ELodShading.NONE": "Ничего"
}