Nuke no longer used files and fix bugs where I'm using the wrong class for doing data formats
This commit is contained in:
@@ -12,7 +12,7 @@ import com.seibel.lod.core.util.*;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
//FIXME: Unused class???
|
||||
//FIXME: To-Be-Used class
|
||||
public class LodBuilder {
|
||||
public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(),
|
||||
() -> Config.Client.Advanced.Debugging.DebugSwitch.logLodBuilderEvent.get());
|
||||
@@ -76,5 +76,5 @@ public class LodBuilder {
|
||||
else // Else, it means someone managed to sneak in a new gen request in this pos. Then lets drop this old task.
|
||||
task.future.complete(null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
import com.seibel.lod.core.a7.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
|
||||
import com.seibel.lod.core.a7.util.IOUtil;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package com.seibel.lod.core.a7.datatype.column;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnFormat;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnQuadView;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.IColumnDatatype;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.*;
|
||||
import com.seibel.lod.core.a7.datatype.column.render.ColumnRenderBuffer;
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.datatype.transform.FullToColumnTransformer;
|
||||
@@ -14,7 +11,6 @@ import com.seibel.lod.core.a7.render.a7LodRenderer;
|
||||
import com.seibel.lod.core.a7.save.io.render.RenderMetaFile;
|
||||
import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.LodDataView;
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
import com.seibel.lod.core.a7.render.LodQuadTree;
|
||||
import com.seibel.lod.core.a7.render.LodRenderSection;
|
||||
@@ -121,7 +117,7 @@ public class ColumnRenderSource implements LodRenderSource, IColumnDatatype {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyVerticalData(LodDataView data, int posX, int posZ, boolean override) {
|
||||
public boolean copyVerticalData(IColumnDataView data, int posX, int posZ, boolean override) {
|
||||
if (DO_SAFETY_CHECKS) {
|
||||
if (data.size() != verticalSize)
|
||||
throw new IllegalArgumentException("data size not the same as vertical size");
|
||||
@@ -137,7 +133,7 @@ public class ColumnRenderSource implements LodRenderSource, IColumnDatatype {
|
||||
} else {
|
||||
if (compare<=0) return false;
|
||||
}
|
||||
data.copyTo(dataContainer, index);
|
||||
data.copyTo(dataContainer, index, data.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+6
-9
@@ -19,11 +19,8 @@
|
||||
|
||||
package com.seibel.lod.core.a7.datatype.column.accessor;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.IColumnDataView;
|
||||
import com.seibel.lod.core.logging.SpamReducedLogger;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -349,8 +346,8 @@ public class ColumnFormat {
|
||||
long tempData;
|
||||
for (int index = 0; index < dataCount; index++) {
|
||||
tempData = sourceData.get(index * inputVerticalSize);
|
||||
allVoid = allVoid && DataPointUtil.isVoid(tempData);
|
||||
allEmpty = allEmpty && !DataPointUtil.doesItExist(tempData);
|
||||
allVoid = allVoid && ColumnFormat.isVoid(tempData);
|
||||
allEmpty = allEmpty && !ColumnFormat.doesItExist(tempData);
|
||||
}
|
||||
|
||||
//We check if there is any data that's not empty or void
|
||||
@@ -378,9 +375,9 @@ public class ColumnFormat {
|
||||
for (int index = 0; index < dataCount; index++) {
|
||||
if (indeces[index] < inputVerticalSize) {
|
||||
tempData = sourceData.get(index * inputVerticalSize + indeces[index]);
|
||||
if (!DataPointUtil.isVoid(tempData) && DataPointUtil.doesItExist(tempData)) {
|
||||
tempHeight = DataPointUtil.getHeight(tempData);
|
||||
tempDepth = DataPointUtil.getDepth(tempData);
|
||||
if (!ColumnFormat.isVoid(tempData) && ColumnFormat.doesItExist(tempData)) {
|
||||
tempHeight = ColumnFormat.getHeight(tempData);
|
||||
tempDepth = ColumnFormat.getDepth(tempData);
|
||||
if (tempDepth >= newHeight) {
|
||||
//First case
|
||||
//the column we are checking is higher than the current column
|
||||
@@ -455,7 +452,7 @@ public class ColumnFormat {
|
||||
for (int index = 0; index < dataCount; index++) {
|
||||
if (indeces[index] < inputVerticalSize) {
|
||||
tempData = sourceData.get(index * inputVerticalSize + indeces[index]);
|
||||
stillHasDataToCheck |= !DataPointUtil.isVoid(tempData) && DataPointUtil.doesItExist(tempData);
|
||||
stillHasDataToCheck |= !ColumnFormat.isVoid(tempData) && ColumnFormat.doesItExist(tempData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-3
@@ -1,7 +1,5 @@
|
||||
package com.seibel.lod.core.a7.datatype.column.accessor;
|
||||
|
||||
import com.seibel.lod.core.objects.LodDataView;
|
||||
|
||||
public interface IColumnDatatype {
|
||||
byte getDetailOffset();
|
||||
default int getDataSize() {
|
||||
@@ -31,6 +29,6 @@ public interface IColumnDatatype {
|
||||
* This methods will add the data in the given position if certain condition are satisfied
|
||||
* @param override if override is true we can override data created with same generation mode
|
||||
*/
|
||||
boolean copyVerticalData(LodDataView data, int posX, int posZ, boolean override);
|
||||
boolean copyVerticalData(IColumnDataView data, int posX, int posZ, boolean override);
|
||||
void generateData(IColumnDatatype lowerDataContainer, int posX, int posZ);
|
||||
}
|
||||
|
||||
@@ -20,13 +20,12 @@
|
||||
package com.seibel.lod.core.a7.datatype.column.render;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnFormat;
|
||||
import com.seibel.lod.core.a7.render.a7LodRenderer;
|
||||
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodQuadBuilder;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
|
||||
@@ -41,26 +40,26 @@ public class ColumnBox
|
||||
short maxY = (short) (y + ySize);
|
||||
short maxZ = (short) (z + zSize);
|
||||
byte skyLightTop = skyLight;
|
||||
byte skyLightBot = DataPointUtil.doesItExist(botData) ? DataPointUtil.getLightSky(botData) : 0;
|
||||
byte skyLightBot = ColumnFormat.doesItExist(botData) ? ColumnFormat.getLightSky(botData) : 0;
|
||||
|
||||
boolean isTransparent = ColorUtil.getAlpha(color)<255 && a7LodRenderer.transparencyEnabled;
|
||||
boolean isTopTransparent = DataPointUtil.getAlpha(topData)<255 && a7LodRenderer.transparencyEnabled;
|
||||
boolean isBotTransparent = DataPointUtil.getAlpha(botData)<255 && a7LodRenderer.transparencyEnabled;
|
||||
boolean isTopTransparent = ColumnFormat.getAlpha(topData)<255 && a7LodRenderer.transparencyEnabled;
|
||||
boolean isBotTransparent = ColumnFormat.getAlpha(botData)<255 && a7LodRenderer.transparencyEnabled;
|
||||
|
||||
|
||||
// Up direction case
|
||||
//We skip if
|
||||
// current block is not transparent: we check if the adj block is attached and opaque
|
||||
|
||||
boolean skipTop = DataPointUtil.doesItExist(topData) && (DataPointUtil.getDepth(topData) == maxY) && !isTopTransparent;
|
||||
boolean skipBot = DataPointUtil.doesItExist(botData) && (DataPointUtil.getHeight(botData) == y) && !isBotTransparent;
|
||||
boolean skipTop = ColumnFormat.doesItExist(topData) && (ColumnFormat.getDepth(topData) == maxY) && !isTopTransparent;
|
||||
boolean skipBot = ColumnFormat.doesItExist(botData) && (ColumnFormat.getHeight(botData) == y) && !isBotTransparent;
|
||||
if(a7LodRenderer.transparencyEnabled && a7LodRenderer.fakeOceanFloor) {
|
||||
if (!isTransparent && isTopTransparent && DataPointUtil.doesItExist(topData)) {
|
||||
skyLightTop = (byte) LodUtil.clamp(0, 15 - (DataPointUtil.getHeight(topData) - y), 15);
|
||||
ySize = (short) (DataPointUtil.getHeight(topData) - y - 1);
|
||||
if (!isTransparent && isTopTransparent && ColumnFormat.doesItExist(topData)) {
|
||||
skyLightTop = (byte) LodUtil.clamp(0, 15 - (ColumnFormat.getHeight(topData) - y), 15);
|
||||
ySize = (short) (ColumnFormat.getHeight(topData) - y - 1);
|
||||
//y = (short) (DataPointUtil.getHeight(topData) - 2);
|
||||
//ySize = 1;
|
||||
} else if (isTransparent && !isBotTransparent && DataPointUtil.doesItExist(botData)) {
|
||||
} else if (isTransparent && !isBotTransparent && ColumnFormat.doesItExist(botData)) {
|
||||
y = (short) (y + ySize - 1);
|
||||
ySize = 1;
|
||||
}
|
||||
@@ -171,7 +170,7 @@ public class ColumnBox
|
||||
{
|
||||
color = ColorUtil.applyShade(color, MC.getShade(direction));
|
||||
ColumnArrayView dataPoint = adjData;
|
||||
if (dataPoint == null || DataPointUtil.isVoid(dataPoint.get(0)))
|
||||
if (dataPoint == null || ColumnFormat.isVoid(dataPoint.get(0)))
|
||||
{
|
||||
builder.addQuadAdj(direction, x, y, z, w0, wy, color, (byte) 15, blockLight);
|
||||
return;
|
||||
@@ -184,30 +183,30 @@ public class ColumnBox
|
||||
byte nextSkyLight = upSkyLight;
|
||||
boolean isTransparent = ColorUtil.getAlpha(color) < 255 && a7LodRenderer.transparencyEnabled;
|
||||
boolean lastWasTransparent = false;
|
||||
for (i = 0; i < dataPoint.size() && DataPointUtil.doesItExist(adjData.get(i))
|
||||
&& !DataPointUtil.isVoid(adjData.get(i)); i++)
|
||||
for (i = 0; i < dataPoint.size() && ColumnFormat.doesItExist(adjData.get(i))
|
||||
&& !ColumnFormat.isVoid(adjData.get(i)); i++)
|
||||
{
|
||||
long adjPoint = adjData.get(i);
|
||||
|
||||
boolean isAdjTransparent = DataPointUtil.getAlpha(adjPoint) < 255 && a7LodRenderer.transparencyEnabled;
|
||||
boolean isAdjTransparent = ColumnFormat.getAlpha(adjPoint) < 255 && a7LodRenderer.transparencyEnabled;
|
||||
|
||||
if (!isTransparent && isAdjTransparent && a7LodRenderer.transparencyEnabled)
|
||||
continue;
|
||||
|
||||
|
||||
short height = DataPointUtil.getHeight(adjPoint);
|
||||
short depth = DataPointUtil.getDepth(adjPoint);
|
||||
short height = ColumnFormat.getHeight(adjPoint);
|
||||
short depth = ColumnFormat.getDepth(adjPoint);
|
||||
|
||||
if(a7LodRenderer.transparencyEnabled && a7LodRenderer.fakeOceanFloor)
|
||||
{
|
||||
|
||||
if(lastWasTransparent && !isAdjTransparent)
|
||||
{
|
||||
height = (short) (DataPointUtil.getHeight(adjData.get(i-1)) - 1);
|
||||
height = (short) (ColumnFormat.getHeight(adjData.get(i-1)) - 1);
|
||||
}
|
||||
else if(isAdjTransparent && (i + 1) < adjData.size())
|
||||
{
|
||||
if (DataPointUtil.getAlpha(adjData.get(i+1)) == 255)
|
||||
if (ColumnFormat.getAlpha(adjData.get(i+1)) == 255)
|
||||
{
|
||||
depth = (short) (height - 1);
|
||||
}
|
||||
@@ -228,7 +227,7 @@ public class ColumnBox
|
||||
// _______&&: depth ______ < y < maxY
|
||||
if (firstFace)
|
||||
{
|
||||
builder.addQuadAdj(direction, x, y, z, w0, wy, color, DataPointUtil.getLightSky(adjPoint),
|
||||
builder.addQuadAdj(direction, x, y, z, w0, wy, color, ColumnFormat.getLightSky(adjPoint),
|
||||
blockLight);
|
||||
}
|
||||
else
|
||||
@@ -237,7 +236,7 @@ public class ColumnBox
|
||||
if (previousDepth == -1)
|
||||
throw new RuntimeException("Loop error");
|
||||
builder.addQuadAdj(direction, x, y, z, w0, (short) (previousDepth - y), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
ColumnFormat.getLightSky(adjPoint), blockLight);
|
||||
previousDepth = -1;
|
||||
}
|
||||
break;
|
||||
@@ -268,7 +267,7 @@ public class ColumnBox
|
||||
if (firstFace)
|
||||
{
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (y + wy - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
ColumnFormat.getLightSky(adjPoint), blockLight);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -278,7 +277,7 @@ public class ColumnBox
|
||||
if (previousDepth > height)
|
||||
{
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (previousDepth - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
ColumnFormat.getLightSky(adjPoint), blockLight);
|
||||
}
|
||||
previousDepth = -1;
|
||||
}
|
||||
@@ -310,7 +309,7 @@ public class ColumnBox
|
||||
if (firstFace)
|
||||
{
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (y + wy - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
ColumnFormat.getLightSky(adjPoint), blockLight);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -320,7 +319,7 @@ public class ColumnBox
|
||||
if (previousDepth > height)
|
||||
{
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (previousDepth - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
ColumnFormat.getLightSky(adjPoint), blockLight);
|
||||
}
|
||||
previousDepth = -1;
|
||||
}
|
||||
@@ -329,8 +328,8 @@ public class ColumnBox
|
||||
previousDepth = depth;
|
||||
firstFace = false;
|
||||
nextSkyLight = upSkyLight;
|
||||
if (i + 1 < adjData.size() && DataPointUtil.doesItExist(adjData.get(i + 1)))
|
||||
nextSkyLight = DataPointUtil.getLightSky(adjData.get(i + 1));
|
||||
if (i + 1 < adjData.size() && ColumnFormat.doesItExist(adjData.get(i + 1)))
|
||||
nextSkyLight = ColumnFormat.getLightSky(adjData.get(i + 1));
|
||||
lastWasTransparent = isAdjTransparent;
|
||||
}
|
||||
|
||||
|
||||
+7
-6
@@ -2,6 +2,7 @@ package com.seibel.lod.core.a7.datatype.column.render;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.column.ColumnRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnFormat;
|
||||
import com.seibel.lod.core.a7.level.IClientLevel;
|
||||
import com.seibel.lod.core.a7.render.a7LodRenderer;
|
||||
import com.seibel.lod.core.a7.util.UncheckedInterruptedException;
|
||||
@@ -290,8 +291,8 @@ public class ColumnRenderBuffer extends RenderBuffer {
|
||||
UncheckedInterruptedException.throwIfInterrupted();
|
||||
|
||||
ColumnArrayView posData = region.getVerticalDataView(x, z);
|
||||
if (posData.size() == 0 || !DataPointUtil.doesItExist(posData.get(0))
|
||||
|| DataPointUtil.isVoid(posData.get(0)))
|
||||
if (posData.size() == 0 || !ColumnFormat.doesItExist(posData.get(0))
|
||||
|| ColumnFormat.isVoid(posData.get(0)))
|
||||
continue;
|
||||
|
||||
ColumnArrayView[][] adjData = new ColumnArrayView[4][];
|
||||
@@ -365,15 +366,15 @@ public class ColumnRenderBuffer extends RenderBuffer {
|
||||
long data = posData.get(i);
|
||||
// If the data is not renderable (Void or non-existing) we stop since there is
|
||||
// no data left in this position
|
||||
if (DataPointUtil.isVoid(data) || !DataPointUtil.doesItExist(data))
|
||||
if (ColumnFormat.isVoid(data) || !ColumnFormat.doesItExist(data))
|
||||
break;
|
||||
|
||||
long adjDataTop = i - 1 >= 0 ? posData.get(i - 1) : DataPointUtil.EMPTY_DATA;
|
||||
long adjDataBot = i + 1 < posData.size() ? posData.get(i + 1) : DataPointUtil.EMPTY_DATA;
|
||||
long adjDataTop = i - 1 >= 0 ? posData.get(i - 1) : ColumnFormat.EMPTY_DATA;
|
||||
long adjDataBot = i + 1 < posData.size() ? posData.get(i + 1) : ColumnFormat.EMPTY_DATA;
|
||||
|
||||
|
||||
// We send the call to create the vertices
|
||||
if(DataPointUtil.getAlpha(data) == 255 || !a7LodRenderer.transparencyEnabled)
|
||||
if(ColumnFormat.getAlpha(data) == 255 || !a7LodRenderer.transparencyEnabled)
|
||||
{
|
||||
CubicLodTemplate.addLodToBuffer(data, adjDataTop, adjDataBot, adjData, detailLevel,
|
||||
x, z, quadBuilderOpaque, debugMode);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.seibel.lod.core.a7.datatype.full;
|
||||
|
||||
public enum EGenMode {
|
||||
Empty,
|
||||
Surface,
|
||||
Feature,
|
||||
Complete;
|
||||
public static EGenMode get(byte genMode) {
|
||||
return EGenMode.values()[genMode];
|
||||
}
|
||||
public static byte get(EGenMode genMode) {
|
||||
return (byte) genMode.ordinal();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.seibel.lod.core.a7.datatype.full;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.column.ColumnRenderSource;
|
||||
import com.seibel.lod.core.a7.datatype.full.accessor.FullArrayView;
|
||||
import com.seibel.lod.core.a7.datatype.full.accessor.SingleFullArrayView;
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
@@ -8,21 +7,13 @@ import com.seibel.lod.core.a7.pos.DhBlockPos2D;
|
||||
import com.seibel.lod.core.a7.pos.DhLodPos;
|
||||
import com.seibel.lod.core.a7.save.io.file.DataMetaFile;
|
||||
import com.seibel.lod.core.a7.datatype.LodDataSource;
|
||||
import com.seibel.lod.core.a7.util.IdMappingUtil;
|
||||
import com.seibel.lod.core.a7.pos.DhSectionPos;
|
||||
import com.seibel.lod.core.a7.util.UnclosableInputStream;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class FullDataSource extends FullArrayView implements LodDataSource { // 1 chunk
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package com.seibel.lod.core.a7.generation;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.full.ChunkSizedData;
|
||||
import com.seibel.lod.core.a7.util.CombinableResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class GenerationResult implements CombinableResult<GenerationResult> {
|
||||
public final ArrayList<ChunkSizedData> dataList = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public GenerationResult combineWith(GenerationResult b, GenerationResult c, GenerationResult d) {
|
||||
dataList.ensureCapacity(dataList.size() + b.dataList.size() + c.dataList.size() + d.dataList.size());
|
||||
dataList.addAll(b.dataList);
|
||||
dataList.addAll(c.dataList);
|
||||
dataList.addAll(d.dataList);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.seibel.lod.core.a7.save.io;
|
||||
|
||||
public class LevelFileHandler {
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import com.seibel.lod.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import java.io.File;
|
||||
|
||||
public class LocalSaveStructure extends SaveStructure {
|
||||
private static final IMinecraftSharedWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class);
|
||||
|
||||
private File debugPath = new File("");
|
||||
|
||||
// Fit for Client_Server & Server_Only environment
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.seibel.lod.core.a7.util;
|
||||
|
||||
public class IOUtil {
|
||||
public static final String LOD_FILE_EXTENSION = ".lod";
|
||||
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package com.seibel.lod.core.a7.util;
|
||||
|
||||
public class IdMappingUtil {
|
||||
public static final String BLOCKSTATE_ID_AIR = "air";
|
||||
//TODO HERE
|
||||
}
|
||||
+9
-9
@@ -19,12 +19,12 @@
|
||||
|
||||
package com.seibel.lod.core.builders.lodBuilding.bufferBuilding;
|
||||
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnFormat;
|
||||
import com.seibel.lod.core.enums.rendering.EDebugMode;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.a7.datatype.column.accessor.ColumnArrayView;
|
||||
import com.seibel.lod.core.a7.datatype.column.render.ColumnBox;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
@@ -43,14 +43,14 @@ public class CubicLodTemplate
|
||||
{
|
||||
short width = (short) (1 << detailLevel);
|
||||
short x = (short) LevelPosUtil.convert(detailLevel, offsetPosX, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
short y = DataPointUtil.getDepth(data);
|
||||
short y = ColumnFormat.getDepth(data);
|
||||
short z = (short) LevelPosUtil.convert(detailLevel, offsetOosZ, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
short dy = (short) (DataPointUtil.getHeight(data) - y);
|
||||
short dy = (short) (ColumnFormat.getHeight(data) - y);
|
||||
if (dy == 0)
|
||||
return;
|
||||
if (dy < 0)
|
||||
{
|
||||
throw new IllegalArgumentException("Negative y size for the data! Data: " + DataPointUtil.toString(data));
|
||||
throw new IllegalArgumentException("Negative y size for the data! Data: " + ColumnFormat.toString(data));
|
||||
}
|
||||
|
||||
int color;
|
||||
@@ -62,9 +62,9 @@ public class CubicLodTemplate
|
||||
float saturationMultiplier = (float)CONFIG.client().graphics().advancedGraphics().getSaturationMultiplier();
|
||||
float brightnessMultiplier = (float)CONFIG.client().graphics().advancedGraphics().getBrightnessMultiplier();
|
||||
if (saturationMultiplier == 1.0 && brightnessMultiplier == 1.0) {
|
||||
color = DataPointUtil.getColor(data);
|
||||
color = ColumnFormat.getColor(data);
|
||||
} else {
|
||||
float[] ahsv = ColorUtil.argbToAhsv(DataPointUtil.getColor(data));
|
||||
float[] ahsv = ColorUtil.argbToAhsv(ColumnFormat.getColor(data));
|
||||
color = ColorUtil.ahsvToArgb(ahsv[0], ahsv[1], ahsv[2] * saturationMultiplier, ahsv[3] * brightnessMultiplier);
|
||||
//ApiShared.LOGGER.info("Raw color:[{}], AHSV:{}, Out color:[{}]",
|
||||
// ColorUtil.toString(DataPointUtil.getColor(data)),
|
||||
@@ -82,7 +82,7 @@ public class CubicLodTemplate
|
||||
case SHOW_GENMODE:
|
||||
case SHOW_GENMODE_WIREFRAME:
|
||||
{
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[DataPointUtil.getGenerationMode(data)];
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[ColumnFormat.getGenerationMode(data)];
|
||||
fullBright = true;
|
||||
break;
|
||||
}
|
||||
@@ -100,8 +100,8 @@ public class CubicLodTemplate
|
||||
width, dy, width, // setWidth
|
||||
x, y, z, // setOffset
|
||||
color, // setColor
|
||||
DataPointUtil.getLightSky(data), // setSkyLights
|
||||
fullBright ? 15 : DataPointUtil.getLightBlock(data), // setBlockLights
|
||||
ColumnFormat.getLightSky(data), // setSkyLights
|
||||
fullBright ? 15 : ColumnFormat.getLightBlock(data), // setBlockLights
|
||||
topData, botData, adjData); // setAdjData
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,9 @@ import com.seibel.lod.core.a7.generation.IChunkGenerator;
|
||||
import com.seibel.lod.core.a7.level.ILevel;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.enums.config.EDistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.EGenerationPriority;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.objects.PosToGenerateContainer;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
|
||||
@@ -141,25 +141,11 @@ public class Config
|
||||
+ " but will increase memory and GPU usage.")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<EDropoffQuality> dropoffQuality = new ConfigEntry.Builder<EDropoffQuality>()
|
||||
.set(EDropoffQuality.AUTO)
|
||||
.comment(""
|
||||
+ "This determines how lod level drop off will be done. \n"
|
||||
+ "\n"
|
||||
+ EDropoffQuality.SMOOTH_DROPOFF + ": \n"
|
||||
+ " The lod level is calculated for each point, making the drop off a smooth circle. \n"
|
||||
+ EDropoffQuality.PERFORMANCE_FOCUSED + ": \n"
|
||||
+ " One detail level for an entire region. Minimize CPU usage and \n"
|
||||
+ " improve terrain refresh delay, especially for high Lod render distance. \n"
|
||||
+ EDropoffQuality.AUTO + ": \n"
|
||||
+ " Use "+ EDropoffQuality.SMOOTH_DROPOFF + " for less then 128 Lod render distance, \n"
|
||||
+ " or "+ EDropoffQuality.PERFORMANCE_FOCUSED +" otherwise.")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<ETransparency> transparency = new ConfigEntry.Builder<ETransparency>()
|
||||
.set(ETransparency.COMPLETE)
|
||||
.comment("")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Integer> lodBiomeBlending = new ConfigEntry.Builder<Integer>()
|
||||
.setMinDefaultMax(0,1,7)
|
||||
.comment(""
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class ColorFormat
|
||||
{
|
||||
public final static int BLUE_SHIFT = 0;
|
||||
public final static int GREEN_SHIFT = BLUE_SHIFT + 8;
|
||||
public final static int RED_SHIFT = BLUE_SHIFT + 16;
|
||||
public final static int ALPHA_SHIFT = BLUE_SHIFT + 24;
|
||||
|
||||
public final static long ALPHA_MASK = 0b1111;
|
||||
public final static long RED_MASK = 0b1111_1111;
|
||||
public final static long GREEN_MASK = 0b1111_1111;
|
||||
public final static long BLUE_MASK = 0b1111_1111;
|
||||
|
||||
public static int createColorData(int alpha, int red, int green, int blue)
|
||||
{
|
||||
int colorData = 0;
|
||||
colorData += (alpha & ALPHA_MASK) << ALPHA_SHIFT;
|
||||
colorData += (red & RED_MASK) << RED_SHIFT;
|
||||
colorData += (green & GREEN_MASK) << GREEN_SHIFT;
|
||||
colorData += (blue & BLUE_MASK) << BLUE_SHIFT;
|
||||
|
||||
return colorData;
|
||||
}
|
||||
|
||||
public static short getAlpha(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK);
|
||||
}
|
||||
|
||||
public static short getRed(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK);
|
||||
}
|
||||
|
||||
public static short getGreen(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK);
|
||||
}
|
||||
|
||||
public static short getBlue(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK);
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
@Deprecated //Unused
|
||||
public class DataMergeUtil
|
||||
{
|
||||
public static void shrinkArray(short[] array, int packetSize, int start, int length, int arraySize)
|
||||
{
|
||||
start *= packetSize;
|
||||
length *= packetSize;
|
||||
arraySize *= packetSize;
|
||||
for (int i = 0; i < arraySize - start; i++)
|
||||
{
|
||||
array[start + i] = array[start + length + i];
|
||||
//remove comment to not leave garbage at the end
|
||||
//array[start + packetSize + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static void extendArray(short[] array, int packetSize, int start, int length, int arraySize)
|
||||
{
|
||||
start *= packetSize;
|
||||
length *= packetSize;
|
||||
arraySize *= packetSize;
|
||||
for (int i = arraySize - start - 1; i >= 0; i--)
|
||||
{
|
||||
array[start + length + i] = array[start + i];
|
||||
array[start + i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class LightFormat
|
||||
{
|
||||
public final static byte INT_BLOCK_LIGHT_SHIFT = 16;
|
||||
public final static byte INT_SKY_LIGHT_SHIFT = 0;
|
||||
|
||||
public final static byte BYTE_BLOCK_LIGHT_SHIFT = 4;
|
||||
public final static byte BYTE_SKY_LIGHT_SHIFT = 0;
|
||||
|
||||
public final static byte BLOCK_LIGHT_MASK = 0b1111;
|
||||
public final static byte SKY_LIGHT_MASK = 0b1111;
|
||||
|
||||
|
||||
public static byte formatLightAsByte(byte skyLight, byte blockLight)
|
||||
{
|
||||
return (byte) (((skyLight & SKY_LIGHT_MASK) << (BYTE_SKY_LIGHT_SHIFT + 4)) | ((blockLight & BLOCK_LIGHT_MASK) << (BYTE_BLOCK_LIGHT_SHIFT + 4)));
|
||||
}
|
||||
|
||||
public static int formatLightAsInt(byte skyLight, byte blockLight)
|
||||
{
|
||||
return ((skyLight & SKY_LIGHT_MASK) << INT_SKY_LIGHT_SHIFT) | ((blockLight & BLOCK_LIGHT_MASK) << INT_BLOCK_LIGHT_SHIFT);
|
||||
}
|
||||
|
||||
public static int convertByteToIntFormat(byte lights)
|
||||
{
|
||||
return formatLightAsInt((byte) ((lights >>> BYTE_SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK), (byte) ((lights >>> BYTE_BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK));
|
||||
}
|
||||
|
||||
public static byte getSkyLight(byte lights)
|
||||
{
|
||||
return (byte) ((lights >>> BYTE_SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
|
||||
}
|
||||
|
||||
public static byte getBlockLight(byte lights)
|
||||
{
|
||||
return (byte) ((lights >>> BYTE_BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK);
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class PositionDataFormat
|
||||
{
|
||||
public final static byte LOD_COUNT_SHIFT = 6;
|
||||
public final static byte CORRECT_LIGHT_SHIFT = 5;
|
||||
public final static byte GEN_TYPE_SHIFT = 2;
|
||||
public final static byte VOID_SHIFT = 1;
|
||||
public final static byte EXISTENCE_SHIFT = 0;
|
||||
|
||||
//We are able to count up to 64 different lods in a column
|
||||
public final static short LOD_COUNT_MASK = 0b11_1111;
|
||||
public final static short CORRECT_LIGHT_MASK = 0b1;
|
||||
public final static short GEN_TYPE_MASK = 0b111;
|
||||
public final static short VOID_MASK = 0b1;
|
||||
public final static short EXISTENCE_MASK = 0b1;
|
||||
|
||||
public final static int EMPTY_DATA = 0;
|
||||
public final static int VOID_DATA = VOID_MASK<<VOID_SHIFT + EXISTENCE_MASK<<EXISTENCE_SHIFT;
|
||||
|
||||
public static short createVoidPositionData(byte generationMode)
|
||||
{
|
||||
short positionData = 0;
|
||||
positionData |= (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
|
||||
positionData |= VOID_MASK << VOID_SHIFT;
|
||||
positionData |= EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
|
||||
return positionData;
|
||||
}
|
||||
|
||||
public static short createPositionData(int lodCount, boolean correctLight, byte generationMode)
|
||||
{
|
||||
short positionData = 0;
|
||||
positionData |= (lodCount & LOD_COUNT_MASK) << LOD_COUNT_SHIFT;
|
||||
positionData |= (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
|
||||
if (correctLight)
|
||||
positionData |= CORRECT_LIGHT_MASK << CORRECT_LIGHT_SHIFT;
|
||||
positionData |= EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
|
||||
return positionData;
|
||||
}
|
||||
|
||||
public static byte getLodCount(short dataPoint)
|
||||
{
|
||||
return (byte) ((dataPoint >>> LOD_COUNT_SHIFT) & LOD_COUNT_MASK);
|
||||
}
|
||||
public static boolean getFlag(short dataPoint)
|
||||
{
|
||||
return ((dataPoint >>> CORRECT_LIGHT_SHIFT) & CORRECT_LIGHT_MASK) == 1;
|
||||
}
|
||||
public static byte getGenerationMode(short dataPoint)
|
||||
{
|
||||
return (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK);
|
||||
}
|
||||
public static boolean isVoid(short dataPoint)
|
||||
{
|
||||
return (((dataPoint >>> VOID_SHIFT) & VOID_MASK) == 1);
|
||||
}
|
||||
public static boolean doesItExist(short dataPoint)
|
||||
{
|
||||
return (((dataPoint >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1);
|
||||
}
|
||||
|
||||
public static short setLodCount(short dataPoint, short lodCount)
|
||||
{
|
||||
return (short) (dataPoint | ((lodCount & LOD_COUNT_MASK) << LOD_COUNT_SHIFT));
|
||||
}
|
||||
public static short setFlag(short dataPoint)
|
||||
{
|
||||
return (short) (dataPoint | ((CORRECT_LIGHT_MASK) << CORRECT_LIGHT_SHIFT));
|
||||
}
|
||||
public static short setGenerationMode(short dataPoint, byte generationMode)
|
||||
{
|
||||
return (short) (dataPoint | ((generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT));
|
||||
}
|
||||
public static short setVoid(short dataPoint)
|
||||
{
|
||||
return (short) (dataPoint | (VOID_MASK << VOID_SHIFT));
|
||||
}
|
||||
public static short setExistence(short dataPoint)
|
||||
{
|
||||
return (short) (dataPoint | (EXISTENCE_MASK << EXISTENCE_SHIFT));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.dataFormat;
|
||||
|
||||
public class VerticalDataFormat
|
||||
{
|
||||
public final static short MIN_WORLD_HEIGHT = -2048;
|
||||
public final static short MAX_WORLD_HEIGHT = 2047;
|
||||
|
||||
public final static byte HEIGHT_SHIFT = 20;
|
||||
public final static byte DEPTH_SHIFT = 8;
|
||||
public final static byte LEVEL_SHIFT = 3;
|
||||
public final static byte BOTTOM_TYPE_SHIFT = 2;
|
||||
public final static byte TRANSPARENCY_SHIFT = 1;
|
||||
public final static byte EXISTENCE_SHIFT = 0;
|
||||
|
||||
|
||||
public final static int FULL_MASK = ~0;
|
||||
|
||||
public final static int HEIGHT_MASK = 0b1111_1111_1111;
|
||||
public final static int DEPTH_MASK = 0b1111_1111_1111;
|
||||
public final static int LEVEL_MASK = 0b111;
|
||||
public final static int TRANSPARENCY_MASK = 0b1;
|
||||
public final static int BOTTOM_TYPE_MASK = 0b1;
|
||||
public final static int EXISTENCE_MASK = 0b1;
|
||||
|
||||
|
||||
public final static int HEIGHT_RESET = ~(HEIGHT_MASK << HEIGHT_SHIFT);
|
||||
public final static int DEPTH_RESET = ~(DEPTH_MASK << DEPTH_SHIFT);
|
||||
public final static int LEVEL_RESET = ~(LEVEL_MASK << LEVEL_SHIFT);
|
||||
public final static int TRANSPARENCY_RESET = ~(TRANSPARENCY_MASK << BOTTOM_TYPE_SHIFT);
|
||||
public final static int BOTTOM_TYPE_RESET = ~(BOTTOM_TYPE_MASK << TRANSPARENCY_SHIFT);
|
||||
public final static int EXISTENCE_RESET = ~(EXISTENCE_MASK << EXISTENCE_SHIFT);
|
||||
|
||||
public final static int EMPTY_LOD = 0;
|
||||
|
||||
|
||||
public static int createVerticalData(int height, int depth, int level, boolean transparent, boolean bottom)
|
||||
{
|
||||
int verticalData = 0;
|
||||
verticalData |= (height & HEIGHT_MASK) << HEIGHT_SHIFT;
|
||||
verticalData |= (depth & DEPTH_MASK) << DEPTH_SHIFT;
|
||||
verticalData |= (level & LEVEL_MASK) << LEVEL_SHIFT;
|
||||
if (bottom)
|
||||
verticalData |= BOTTOM_TYPE_MASK << BOTTOM_TYPE_SHIFT;
|
||||
if (transparent)
|
||||
verticalData |= TRANSPARENCY_MASK << TRANSPARENCY_SHIFT;
|
||||
verticalData |= EXISTENCE_MASK << EXISTENCE_SHIFT;
|
||||
|
||||
return verticalData;
|
||||
}
|
||||
|
||||
public static short getHeight(int verticalData)
|
||||
{
|
||||
return (short) ((verticalData >>> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
}
|
||||
|
||||
public static short getDepth(int verticalData)
|
||||
{
|
||||
return (short) ((verticalData >>> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
}
|
||||
|
||||
public static byte getLevel(int verticalData)
|
||||
{
|
||||
return (byte) ((verticalData >>> LEVEL_SHIFT) & LEVEL_MASK);
|
||||
}
|
||||
|
||||
public static boolean isTransparent(int verticalData)
|
||||
{
|
||||
return ((verticalData >>> TRANSPARENCY_SHIFT) & TRANSPARENCY_MASK) == 1;
|
||||
}
|
||||
|
||||
public static boolean isBottom(int verticalData)
|
||||
{
|
||||
return ((verticalData >>> BOTTOM_TYPE_SHIFT) & BOTTOM_TYPE_MASK) == 1;
|
||||
}
|
||||
|
||||
public static boolean doesItExist(int verticalData)
|
||||
{
|
||||
return (((verticalData >>> EXISTENCE_SHIFT) & EXISTENCE_MASK) == 1);
|
||||
}
|
||||
|
||||
|
||||
public static int setHeight(int verticalData, int height)
|
||||
{
|
||||
return verticalData | ((height & HEIGHT_MASK) << HEIGHT_SHIFT);
|
||||
}
|
||||
|
||||
public static int setDepth(int verticalData, int depth)
|
||||
{
|
||||
return verticalData | ((depth & DEPTH_MASK) << DEPTH_SHIFT);
|
||||
}
|
||||
|
||||
public static int setLevel(int verticalData, int level)
|
||||
{
|
||||
return verticalData | ((level & LEVEL_MASK) << LEVEL_SHIFT);
|
||||
}
|
||||
|
||||
public static int setTransparency(int verticalData)
|
||||
{
|
||||
return verticalData | ((TRANSPARENCY_MASK) << TRANSPARENCY_SHIFT);
|
||||
}
|
||||
|
||||
public static int setBottom(int verticalData)
|
||||
{
|
||||
return verticalData | ((BOTTOM_TYPE_MASK) << BOTTOM_TYPE_SHIFT);
|
||||
}
|
||||
|
||||
public static int setExistence(int verticalData)
|
||||
{
|
||||
return verticalData | ((EXISTENCE_MASK) << EXISTENCE_SHIFT);
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,6 @@ package com.seibel.lod.core.enums;
|
||||
* @author James Seibel
|
||||
* @version 2022-7-13
|
||||
*/
|
||||
@Deprecated
|
||||
public enum ELevelType
|
||||
{
|
||||
SERVER_LEVEL,
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2022 Tom Lee (TomTheFurry)
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.enums.config;
|
||||
|
||||
/**
|
||||
* AUTO <br>
|
||||
* SMOOTH_DROPOFF <br>
|
||||
* PERFORMANCE_FOCUSED <br> <br>
|
||||
*
|
||||
* Determines how lod level drop off should be done
|
||||
*
|
||||
* @author Tom Lee
|
||||
* @version 7-1-2022
|
||||
*/
|
||||
public enum EDropoffQuality
|
||||
{
|
||||
// Reminder:
|
||||
// when adding items up the API minor version
|
||||
// when removing items up the API major version
|
||||
|
||||
|
||||
/** SMOOTH_DROPOFF when <128 lod view distance, or PERFORMANCE_FOCUSED otherwise */
|
||||
AUTO(-1),
|
||||
|
||||
SMOOTH_DROPOFF(10),
|
||||
|
||||
PERFORMANCE_FOCUSED(0);
|
||||
|
||||
public final int fastModeSwitch;
|
||||
|
||||
EDropoffQuality(int fastModeSwitch) {
|
||||
this.fastModeSwitch = fastModeSwitch;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.handlers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Cola
|
||||
* @author Leonardo Amato
|
||||
* @version 11-12-2021
|
||||
*/
|
||||
public class ChunkFileLoader
|
||||
{
|
||||
// TODO
|
||||
// public static IChunk getChunkFromFile(ChunkPos pos)
|
||||
// {
|
||||
// LevelWrapper clientLevel = MinecraftWrapper.INSTANCE.getWrappedClientLevel();
|
||||
// if (clientLevel == null)
|
||||
// return null;
|
||||
// WorldWrapper serverWorld = LodUtil.getServerWorldFromDimension(clientLevel.getDimensionType());
|
||||
// try
|
||||
// {
|
||||
// File file = new File(serverWorld.getSaveFolder().getParent() + File.separatorChar + "region", "r." + (pos.x >> 5) + "." + (pos.z >> 5) + ".mca");
|
||||
// if(!file.exists())
|
||||
// return null;
|
||||
// IChunk loadedChunk = ChunkSerializer.read(
|
||||
// serverWorld,
|
||||
// serverWorld.getStructureManager(),
|
||||
// serverWorld.getPoiManager(),
|
||||
// pos,
|
||||
// serverWorld.getChunkSource().chunkMap.read(pos)
|
||||
// );
|
||||
// boolean emptyChunk = true;
|
||||
// for(int i = 0; i < 16; i++){
|
||||
// for(int j = 0; j < 16; j++){
|
||||
// emptyChunk &= loadedChunk.isYSpaceEmpty(i,j);
|
||||
// }
|
||||
// }
|
||||
// if(emptyChunk)
|
||||
// return null;
|
||||
// else
|
||||
// return loadedChunk;
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects;
|
||||
|
||||
/*
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.BlockDetail;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class BlockBiomeCouple
|
||||
{
|
||||
public static final ConcurrentMap<BlockDetail, BlockBiomeCouple> noBiomeInstanceCache = new ConcurrentHashMap<>();
|
||||
public static ConcurrentMap<IBiomeWrapper, ConcurrentMap<BlockDetail, BlockBiomeCouple>> withBiomeInstanceCache = new ConcurrentHashMap<>();
|
||||
|
||||
String blockName;
|
||||
String biomeName;
|
||||
String coupleName;
|
||||
|
||||
IBiomeWrapper biomeColor;
|
||||
BlockDetail blockColor;
|
||||
|
||||
public static void addBlockBiomeToCache(IBlockColorWrapper blockColor){
|
||||
}
|
||||
|
||||
public static BlockBiomeCouple getBlockBiomeCouple(IBlockColorWrapper blockColor){
|
||||
if(noBiomeInstanceCache.containsKey(blockColor))
|
||||
{
|
||||
return noBiomeInstanceCache.get(blockColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockBiomeCouple couple = new BlockBiomeCouple(blockColor);
|
||||
noBiomeInstanceCache.put(blockColor,couple);
|
||||
return couple;
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockBiomeCouple getBlockBiomeCouple(IBiomeWrapper biomeColor, IBlockColorWrapper blockColor){
|
||||
if(biomeColor == null)
|
||||
{
|
||||
return getBlockBiomeCouple(blockColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(withBiomeInstanceCache.containsKey(biomeColor))
|
||||
{
|
||||
withBiomeInstanceCache.put(biomeColor, new ConcurrentHashMap<>());
|
||||
}
|
||||
ConcurrentMap<IBlockColorWrapper, BlockBiomeCouple> blockToCoupleMap = withBiomeIstanceCache.get(biomeColor);
|
||||
if(blockToCoupleMap.containsKey(blockColor))
|
||||
{
|
||||
return blockToCoupleMap.get(blockColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlockBiomeCouple couple = new BlockBiomeCouple(blockColor,biomeColor);
|
||||
blockToCoupleMap.put(blockColor,couple);
|
||||
return couple;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockBiomeCouple(IBlockColorWrapper blockColor)
|
||||
{
|
||||
this.biomeColor = null;
|
||||
this.blockColor = blockColor;
|
||||
biomeName = "";
|
||||
blockName = blockColor.getName();
|
||||
coupleName = blockName;
|
||||
}
|
||||
|
||||
public BlockBiomeCouple(IBlockColorWrapper blockColor, IBiomeWrapper biomeColor)
|
||||
{
|
||||
this.biomeColor = biomeColor;
|
||||
this.blockColor = blockColor;
|
||||
|
||||
if(biomeColor == null)
|
||||
biomeName = biomeColor.getName();
|
||||
else
|
||||
biomeName = "";
|
||||
|
||||
blockName = blockColor.getName();
|
||||
|
||||
coupleName = blockName + biomeName;
|
||||
}
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BlockBiomeCouple))
|
||||
return false;
|
||||
BlockBiomeCouple that = (BlockBiomeCouple) o;
|
||||
return Objects.equals(blockName, that.blockName) && Objects.equals(biomeName, that.biomeName);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(blockName, biomeName);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects;
|
||||
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
/**
|
||||
* This object is similar to ChunkPos or BlockPos.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 8-21-2021
|
||||
*/
|
||||
public class DHRegionPos
|
||||
{
|
||||
|
||||
public int x;
|
||||
public int z;
|
||||
|
||||
/** Sets x and z to 0 */
|
||||
public DHRegionPos()
|
||||
{
|
||||
x = 0;
|
||||
z = 0;
|
||||
}
|
||||
|
||||
/** simple constructor that sets x and z to new x and z. */
|
||||
public DHRegionPos(int newX, int newZ)
|
||||
{
|
||||
x = newX;
|
||||
z = newZ;
|
||||
}
|
||||
|
||||
/** Converts from a BlockPos to a RegionPos */
|
||||
public DHRegionPos(DHBlockPos pos)
|
||||
{
|
||||
x = Math.floorDiv(pos.x >> 4, LodUtil.REGION_WIDTH_IN_CHUNKS);
|
||||
z = Math.floorDiv(pos.z >> 4, LodUtil.REGION_WIDTH_IN_CHUNKS);
|
||||
}
|
||||
|
||||
/** Converts from a ChunkPos to a RegionPos */
|
||||
public DHRegionPos(DHChunkPos pos)
|
||||
{
|
||||
x = Math.floorDiv(pos.getX(), LodUtil.REGION_WIDTH_IN_CHUNKS);
|
||||
z = Math.floorDiv(pos.getZ(), LodUtil.REGION_WIDTH_IN_CHUNKS);
|
||||
}
|
||||
|
||||
public DHChunkPos centerChunkPos() {
|
||||
return new DHChunkPos(x * LodUtil.REGION_WIDTH_IN_CHUNKS + LodUtil.REGION_WIDTH_IN_CHUNKS / 2,
|
||||
z * LodUtil.REGION_WIDTH_IN_CHUNKS + LodUtil.REGION_WIDTH_IN_CHUNKS / 2);
|
||||
}
|
||||
public DHChunkPos cornerChunkPos() {
|
||||
return new DHChunkPos(x * LodUtil.REGION_WIDTH_IN_CHUNKS, z * LodUtil.REGION_WIDTH_IN_CHUNKS);
|
||||
}
|
||||
public DHBlockPos centerBlockPos() {
|
||||
return new DHBlockPos(x * LodUtil.REGION_WIDTH_IN_CHUNKS * 16 + LodUtil.REGION_WIDTH_IN_CHUNKS * 16 / 2,
|
||||
0, z * LodUtil.REGION_WIDTH_IN_CHUNKS * 16 + LodUtil.REGION_WIDTH_IN_CHUNKS * 16 / 2);
|
||||
}
|
||||
public DHBlockPos cornerBlockPos() {
|
||||
return new DHBlockPos(x * LodUtil.REGION_WIDTH_IN_CHUNKS * 16,
|
||||
0, z * LodUtil.REGION_WIDTH_IN_CHUNKS * 16);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
// If the object is compared with itself then return true
|
||||
if (o == this) {
|
||||
return true;
|
||||
}
|
||||
// Check if o is an instance of RegionPos or not
|
||||
if (!(o instanceof DHRegionPos)) {
|
||||
return false;
|
||||
}
|
||||
DHRegionPos c = (DHRegionPos) o;
|
||||
return c.x==x &&c.z==z;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "(" + x + "," + z + ")";
|
||||
}
|
||||
|
||||
public static long asLong(int i, int j) {
|
||||
return (long)i & 0xFFFFFFFFL | ((long)j & 0xFFFFFFFFL) << 32;
|
||||
}
|
||||
public static int getX(long l) {
|
||||
return (int)(l & 0xFFFFFFFFL);
|
||||
}
|
||||
public static int getZ(long l) {
|
||||
return (int)(l >>> 32 & 0xFFFFFFFFL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Long.hashCode(asLong(x,z));
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
package com.seibel.lod.core.objects;
|
||||
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
|
||||
public final class LodDataView {
|
||||
private final long[] data;
|
||||
private final int size;
|
||||
private final int offset;
|
||||
public LodDataView(long[] data, int size, int offset) {
|
||||
this.data = data;
|
||||
this.size = size;
|
||||
this.offset = offset;
|
||||
}
|
||||
public long get(int index) {
|
||||
return data[index + offset];
|
||||
}
|
||||
public void set(int index, long value) {
|
||||
data[index + offset] = value;
|
||||
}
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
public void copyTo(long[] target, int offset) {
|
||||
System.arraycopy(data, this.offset, target, offset, size);
|
||||
}
|
||||
public void copyTo(LodDataView target) {
|
||||
System.arraycopy(data, this.offset, target.data, target.offset, size);
|
||||
}
|
||||
|
||||
public boolean mergeWith(LodDataView source, int verticalSize, boolean override) {
|
||||
if (size != source.size) {
|
||||
throw new IllegalArgumentException("Cannot merge views of different sizes");
|
||||
}
|
||||
boolean anyChange = false;
|
||||
for (int o=0; o<(source.size()*verticalSize); o+=verticalSize) {
|
||||
if (override) {
|
||||
if (DataPointUtil.compareDatapointPriority(source.get(o), get(o)) >= 0) {
|
||||
anyChange = true;
|
||||
System.arraycopy(source.data, source.offset+o, data, offset+o, verticalSize);
|
||||
}
|
||||
} else {
|
||||
if (DataPointUtil.compareDatapointPriority(source.get(o), get(o)) > 0) {
|
||||
anyChange = true;
|
||||
System.arraycopy(source.data, source.offset+o, data, offset+o, verticalSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
return anyChange;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -33,9 +33,9 @@ public class ParsedIp
|
||||
|
||||
/**
|
||||
* Can be used to find if a numeric IP is a LAN IP
|
||||
*
|
||||
*
|
||||
* Ip list source: <br>
|
||||
* https://networkengineering.stackexchange.com/questions/5825/why-192-168-for-local-addresses
|
||||
* <a href="https://networkengineering.stackexchange.com/questions/5825/why-192-168-for-local-addresses">...</a>
|
||||
*/
|
||||
public static final String LAN_IP_REGEX = "(10|172\\.16|192\\.168).*";
|
||||
|
||||
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects;
|
||||
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
|
||||
/**
|
||||
* Holds the levelPos that need to be generated.
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 9-27-2021
|
||||
*/
|
||||
public class PosToGenerateContainer
|
||||
{
|
||||
private final int playerPosX;
|
||||
private final int playerPosZ;
|
||||
private int nearSize;
|
||||
private int farSize;
|
||||
|
||||
// TODO what is the format of these two arrays? [detailLevel][4-children]?
|
||||
private final int[][] nearPosToGenerate;
|
||||
private final int[][] farPosToGenerate;
|
||||
|
||||
public PosToGenerateContainer(int maxDataToGenerate, int playerPosX, int playerPosZ)
|
||||
{
|
||||
this.playerPosX = playerPosX;
|
||||
this.playerPosZ = playerPosZ;
|
||||
nearSize = 0;
|
||||
farSize = 0;
|
||||
nearPosToGenerate = new int[maxDataToGenerate][4];
|
||||
farPosToGenerate = new int[maxDataToGenerate][4];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO what is going on in this method?
|
||||
public void addNearPosToGenerate(byte detailLevel, int posX, int posZ, boolean sort)
|
||||
{
|
||||
// FIXME: This is a cast from double to int!!! OVERFLOW MAY HAPPEN!
|
||||
int distance = (int)LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ);
|
||||
int index;
|
||||
|
||||
//We are introducing a position in the near array
|
||||
|
||||
index = nearSize;
|
||||
if (index == nearPosToGenerate.length) {
|
||||
if (Integer.compare(distance, nearPosToGenerate[index - 1][3]) > 0) {
|
||||
return;
|
||||
}
|
||||
index--;
|
||||
} else nearSize++;
|
||||
|
||||
if (sort) {
|
||||
while (index > 0 && Integer.compare(distance, nearPosToGenerate[index - 1][3]) <= 0)
|
||||
{
|
||||
nearPosToGenerate[index][0] = nearPosToGenerate[index - 1][0];
|
||||
nearPosToGenerate[index][1] = nearPosToGenerate[index - 1][1];
|
||||
nearPosToGenerate[index][2] = nearPosToGenerate[index - 1][2];
|
||||
nearPosToGenerate[index][3] = nearPosToGenerate[index - 1][3];
|
||||
index--;
|
||||
}
|
||||
}
|
||||
nearPosToGenerate[index][0] = detailLevel + 1;
|
||||
nearPosToGenerate[index][1] = posX;
|
||||
nearPosToGenerate[index][2] = posZ;
|
||||
nearPosToGenerate[index][3] = distance;
|
||||
}
|
||||
|
||||
// TODO what is going on in this method?
|
||||
public void addFarPosToGenerate(byte detailLevel, int posX, int posZ, boolean sort)
|
||||
{
|
||||
// FIXME: This is a cast from double to int!!! OVERFLOW MAY HAPPEN!
|
||||
int distance = (int)LevelPosUtil.minDistance(detailLevel, posX, posZ, playerPosX, playerPosZ);
|
||||
int index;
|
||||
|
||||
// We are introducing a position in the far array
|
||||
|
||||
index = farSize;
|
||||
if (index == farPosToGenerate.length) {
|
||||
if (Integer.compare(distance, farPosToGenerate[index - 1][3]) > 0) {
|
||||
return;
|
||||
}
|
||||
index--;
|
||||
} else farSize++;
|
||||
|
||||
if (sort) {
|
||||
while (index > 0 && Integer.compare(distance, farPosToGenerate[index - 1][3]) <= 0)
|
||||
{
|
||||
farPosToGenerate[index][0] = farPosToGenerate[index - 1][0];
|
||||
farPosToGenerate[index][1] = farPosToGenerate[index - 1][1];
|
||||
farPosToGenerate[index][2] = farPosToGenerate[index - 1][2];
|
||||
farPosToGenerate[index][3] = farPosToGenerate[index - 1][3];
|
||||
index--;
|
||||
}
|
||||
}
|
||||
farPosToGenerate[index][0] = detailLevel + 1;
|
||||
farPosToGenerate[index][1] = posX;
|
||||
farPosToGenerate[index][2] = posZ;
|
||||
farPosToGenerate[index][3] = distance;
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return nearSize == nearPosToGenerate.length && farSize == farPosToGenerate.length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getNumberOfPos()
|
||||
{
|
||||
return nearSize + farSize;
|
||||
}
|
||||
|
||||
public int getNumberOfNearPos()
|
||||
{
|
||||
return nearSize;
|
||||
}
|
||||
|
||||
public int getNumberOfFarPos()
|
||||
{
|
||||
return farSize;
|
||||
}
|
||||
|
||||
public int getMaxNumberOfNearPos()
|
||||
{
|
||||
return nearPosToGenerate.length;
|
||||
}
|
||||
|
||||
public int getMaxNumberOfFarPos()
|
||||
{
|
||||
return farPosToGenerate.length;
|
||||
}
|
||||
|
||||
// TODO what does getNth mean? could the name be more descriptive or is it just a index?
|
||||
public int getNthDetail(int n, boolean near)
|
||||
{
|
||||
if (near)
|
||||
return nearPosToGenerate[n][0];
|
||||
else
|
||||
return farPosToGenerate[n][0];
|
||||
}
|
||||
|
||||
public int getNthPosX(int n, boolean near)
|
||||
{
|
||||
if (near)
|
||||
return nearPosToGenerate[n][1];
|
||||
else
|
||||
return farPosToGenerate[n][1];
|
||||
}
|
||||
|
||||
public int getNthPosZ(int n, boolean near)
|
||||
{
|
||||
if (near)
|
||||
return nearPosToGenerate[n][2];
|
||||
else
|
||||
return farPosToGenerate[n][2];
|
||||
}
|
||||
|
||||
public int getNthGeneration(int n, boolean near)
|
||||
{
|
||||
if (near)
|
||||
return nearPosToGenerate[n][3];
|
||||
else
|
||||
return farPosToGenerate[n][3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append('\n');
|
||||
builder.append('\n');
|
||||
builder.append('\n');
|
||||
builder.append("near pos to generate");
|
||||
builder.append('\n');
|
||||
for (int[] ints : nearPosToGenerate)
|
||||
{
|
||||
if (ints[0] == 0)
|
||||
break;
|
||||
builder.append(ints[0] - 1);
|
||||
builder.append(" ");
|
||||
builder.append(ints[1]);
|
||||
builder.append(" ");
|
||||
builder.append(ints[2]);
|
||||
builder.append(" ");
|
||||
builder.append(ints[3]);
|
||||
builder.append('\n');
|
||||
}
|
||||
builder.append('\n');
|
||||
|
||||
builder.append("far pos to generate");
|
||||
builder.append('\n');
|
||||
for (int[] ints : farPosToGenerate)
|
||||
{
|
||||
if (ints[0] == 0)
|
||||
break;
|
||||
builder.append(ints[0] - 1);
|
||||
builder.append(" ");
|
||||
builder.append(ints[1]);
|
||||
builder.append(" ");
|
||||
builder.append(ints[2]);
|
||||
builder.append(" ");
|
||||
builder.append(ints[3]);
|
||||
builder.append('\n');
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects.lod;
|
||||
|
||||
import com.seibel.lod.core.objects.LodDataView;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* A level container is a quad tree level
|
||||
*/
|
||||
public interface LevelContainer
|
||||
{
|
||||
/**
|
||||
* With this you can add data to the level container
|
||||
* @param data actual data to add in an array of long format.
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @param index vertical position in the detail level
|
||||
* @return true if correctly added, false otherwise
|
||||
*/
|
||||
boolean addData(long data, int posX, int posZ, int index);
|
||||
|
||||
/**
|
||||
* With this you can add data to the level container
|
||||
* @param data actual data to add in an array of long[] format.
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return true if correctly changed, false otherwise
|
||||
*/
|
||||
@Deprecated
|
||||
boolean addVerticalData(long[] data, int posX, int posZ, boolean override);
|
||||
boolean copyVerticalData(LodDataView data, int posX, int posZ, boolean override);
|
||||
|
||||
/**
|
||||
* With this you can add a square of data to the level container
|
||||
* @return true if anything changed, false otherwise
|
||||
*/
|
||||
@Deprecated
|
||||
boolean addChunkOfData(long[] data, int posX, int posZ, int widthX, int widthZ, boolean override);
|
||||
boolean copyChunkOfData(LodDataView data, int posX, int posZ, int widthX, int widthZ, boolean override);
|
||||
|
||||
/**
|
||||
* With this you can get data from the level container
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return the data in long array format
|
||||
*/
|
||||
long getData(int posX, int posZ, int index);
|
||||
|
||||
/**
|
||||
* With this you can get data from the level container
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return the data in long array format
|
||||
*/
|
||||
@Deprecated
|
||||
long[] getAllData(int posX, int posZ);
|
||||
LodDataView getVerticalDataView(int posX, int posZ);
|
||||
|
||||
/**
|
||||
* With this you can get data from the level container
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return the data in long array format
|
||||
*/
|
||||
long getSingleData(int posX, int posZ);
|
||||
|
||||
/**
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return true only if the data exist
|
||||
*/
|
||||
boolean doesItExist(int posX, int posZ);
|
||||
|
||||
/**
|
||||
* @return return the detailLevel of this level container
|
||||
*/
|
||||
byte getDetailLevel();
|
||||
|
||||
|
||||
int getVerticalSize();
|
||||
|
||||
/** Clears the dataPoint at the given array index */
|
||||
void clear(int posX, int posZ);
|
||||
|
||||
/**
|
||||
* This return a level container with detail level lower than the current level.
|
||||
* The new level container may use information of this level.
|
||||
* @return the new level container
|
||||
*/
|
||||
LevelContainer expand();
|
||||
|
||||
/**
|
||||
* @param lowerLevelContainer lower level where we extract the data
|
||||
* @param posX x position in the detail level to update
|
||||
* @param posZ z position in the detail level to update
|
||||
*/
|
||||
void updateData(LevelContainer lowerLevelContainer, int posX, int posZ);
|
||||
|
||||
/**
|
||||
* This will write the raw data with metadata to the output stream
|
||||
* @return isAllGenerated whether the data is all generated
|
||||
* @throws IOException
|
||||
*/
|
||||
boolean writeData(DataOutputStream output) throws IOException;
|
||||
|
||||
/**
|
||||
* This will give the data to save in the file
|
||||
* @return data as a String
|
||||
*/
|
||||
int getMaxNumberOfLods();
|
||||
|
||||
/**
|
||||
* This will return a ram usage estimation of this object
|
||||
* @return long as byte
|
||||
*/
|
||||
long getRoughRamUsage();
|
||||
|
||||
}
|
||||
@@ -1,604 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects.lod;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.enums.config.EDistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.EDropoffQuality;
|
||||
import com.seibel.lod.core.enums.config.EGenerationPriority;
|
||||
import com.seibel.lod.core.enums.config.EVerticalQuality;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.objects.*;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
|
||||
/**
|
||||
* This object holds all loaded LevelContainers acting as a quad tree for a
|
||||
* given region. <Br>
|
||||
* <Br>
|
||||
*
|
||||
* <strong>Coordinate Standard: </strong><br>
|
||||
* Coordinate called posX or posZ are relative LevelPos coordinates <br>
|
||||
* unless stated otherwise. <br>
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 10-10-2021
|
||||
*/
|
||||
public class LodRegion {
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonInjector.INSTANCE.get(ILodConfigWrapperSingleton.class);
|
||||
/** Number of detail level supported by a region */
|
||||
private static final byte POSSIBLE_LOD = LodUtil.DETAIL_OPTIONS;
|
||||
|
||||
/** Holds the lowest (least detailed) detail level in this region */
|
||||
private volatile byte minDetailLevel;
|
||||
public byte lastMaxDetailLevel = LodUtil.REGION_DETAIL_LEVEL;
|
||||
|
||||
/**
|
||||
* This holds all data for this region
|
||||
*/
|
||||
private final LevelContainer[] dataContainer;
|
||||
|
||||
/** This chunk Pos has been generated */
|
||||
// private final boolean[] preGeneratedChunkPos;
|
||||
|
||||
/** the vertical quality of this region */
|
||||
private final EVerticalQuality verticalQuality;
|
||||
|
||||
/** this region's x RegionPos */
|
||||
public final int regionPosX;
|
||||
/** this region's z RegionPos */
|
||||
public final int regionPosZ;
|
||||
|
||||
public volatile boolean needRecheckGenPoint = true;
|
||||
//public volatile int needRegenBuffer = 2; MOVED TO RENDERREGION!
|
||||
public volatile boolean needSignalToRegenBuffer = true;
|
||||
public volatile boolean needSaving = false;
|
||||
public final AtomicInteger isWriting = new AtomicInteger(0);
|
||||
|
||||
public static byte calculateFarModeSwitch(byte targetLevel) {
|
||||
if (targetLevel==0) return 0; // Always use detail 0 if it's way too close
|
||||
double part = targetLevel / (double)LodUtil.REGION_DETAIL_LEVEL;
|
||||
byte farModeLevel = LodUtil.DETAIL_OPTIONS-(LodUtil.CHUNK_DETAIL_LEVEL+1);
|
||||
farModeLevel *= part;
|
||||
farModeLevel += (LodUtil.CHUNK_DETAIL_LEVEL+1);
|
||||
return (byte)LodUtil.clamp(LodUtil.CHUNK_DETAIL_LEVEL+1, farModeLevel, LodUtil.DETAIL_OPTIONS - 1);
|
||||
}
|
||||
|
||||
public LodRegion(byte minDetailLevel, DHRegionPos regionPos, EVerticalQuality verticalQuality) {
|
||||
this.minDetailLevel = minDetailLevel;
|
||||
this.regionPosX = regionPos.x;
|
||||
this.regionPosZ = regionPos.z;
|
||||
this.verticalQuality = verticalQuality;
|
||||
dataContainer = new LevelContainer[POSSIBLE_LOD];
|
||||
|
||||
// Initialize all the different matrices
|
||||
for (byte lod = minDetailLevel; lod <= LodUtil.REGION_DETAIL_LEVEL; lod++) {
|
||||
dataContainer[lod] = new VerticalLevelContainer(lod);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the data point into the region.
|
||||
* <p>
|
||||
*
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addData(byte detailLevel, int posX, int posZ, int verticalIndex, long data) {
|
||||
if(isWriting.get()<=0) throw new ConcurrentModificationException("isWriting counter lock should have been acquired!");
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
|
||||
// The dataContainer could have null entries if the
|
||||
// detailLevel changes.
|
||||
if (this.dataContainer[detailLevel] == null)
|
||||
return false;// this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
|
||||
this.dataContainer[detailLevel].addData(data, posX, posZ, verticalIndex);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the vertical data into the region.
|
||||
* <p>
|
||||
*
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addVerticalData(byte detailLevel, int posX, int posZ, long[] data, boolean override) {
|
||||
if(isWriting.get()<=0) throw new ConcurrentModificationException("isWriting counter lock should have been acquired!");
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
|
||||
// The dataContainer could have null entries if the
|
||||
// detailLevel changes.
|
||||
if (this.dataContainer[detailLevel] == null)
|
||||
return false;// this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
|
||||
boolean updated = this.dataContainer[detailLevel].addVerticalData(data, posX, posZ, override);
|
||||
if (updated) {
|
||||
needSignalToRegenBuffer = true;
|
||||
needSaving = true;
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts the vertical data into the region.
|
||||
* <p>
|
||||
*
|
||||
* @return true if the data was added successfully
|
||||
*/
|
||||
public boolean addChunkOfData(byte detailLevel, int posX, int posZ, int widthX, int widthZ, long[] data, int verticalSize, boolean override) {
|
||||
if(isWriting.get()<=0) throw new ConcurrentModificationException("isWriting counter lock should have been acquired!");
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
|
||||
// The dataContainer could have null entries if the
|
||||
// detailLevel changes.
|
||||
if (this.dataContainer[detailLevel] == null)
|
||||
return false;// this.dataContainer[detailLevel] = new VerticalLevelContainer(detailLevel);
|
||||
if (this.dataContainer[detailLevel].getVerticalSize() != verticalSize) {
|
||||
throw new RuntimeException(
|
||||
String.format("Provided data's verticalSize [%d]" +
|
||||
" is different from current storage's verticalSize [%d] at detail [%d]",
|
||||
verticalSize, this.dataContainer[detailLevel].getVerticalSize(), detailLevel));
|
||||
}
|
||||
boolean updated = this.dataContainer[detailLevel].addChunkOfData(data, posX, posZ, widthX, widthZ, override);
|
||||
//ApiShared.LOGGER.info("addChunkOfData(region:{}, level:{}, x:{}, z:{}, wx:{}, wz:{}, override:{}, updated:{})",
|
||||
// getRegionPos(), detailLevel, posX, posZ, widthX, widthZ, override, updated);
|
||||
if (updated) {
|
||||
needSignalToRegenBuffer = true;
|
||||
needSaving = true;
|
||||
} else {
|
||||
/*ApiShared.LOGGER.info("addChunkOfData nothing changed. Datapoint: {}\n Upper Datapoint: {}",
|
||||
DataPointUtil.toString(this.dataContainer[detailLevel].getSingleData(posX, posZ)),
|
||||
DataPointUtil.toString(this.dataContainer[9].getSingleData(0, 0))
|
||||
);*/
|
||||
|
||||
}
|
||||
if (!doesDataExist(detailLevel, posX, posZ, EDistanceGenerationMode.values()[DataPointUtil.getGenerationMode(data[0]) - 1])) { //FIXME: -1 case NONE has value of 1 but slot of 0
|
||||
throw new RuntimeException("Data still doesn't exist after addChunkOfData!");
|
||||
}
|
||||
|
||||
return updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
*
|
||||
* @return the data at the relative pos and detail level, 0 if the data doesn't
|
||||
* exist.
|
||||
*/
|
||||
public long getData(byte detailLevel, int posX, int posZ, int verticalIndex) {
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[detailLevel].getData(posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
*
|
||||
* @return the data at the relative pos and detail level, 0 if the data doesn't
|
||||
* exist.
|
||||
*/
|
||||
@Deprecated
|
||||
public long[] getAllData(byte detailLevel, int posX, int posZ) {
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[detailLevel].getAllData(posX, posZ);
|
||||
}
|
||||
public LodDataView getDataView(byte detailLevel, int posX, int posZ) {
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[detailLevel].getVerticalDataView(posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
*
|
||||
* @return the data at the relative pos and detail level, 0 if the data doesn't
|
||||
* exist.
|
||||
*/
|
||||
public long getSingleData(byte detailLevel, int posX, int posZ) {
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[detailLevel].getSingleData(posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will fill the posToGenerate array with all levelPos that are
|
||||
* render-able.
|
||||
* <p>
|
||||
* TODO why don't we return the posToGenerate, it would make this easier to
|
||||
* understand
|
||||
*/
|
||||
public void getPosToGenerate(PosToGenerateContainer posToGenerate, int playerBlockPosX, int playerBlockPosZ,
|
||||
EGenerationPriority priority, EDistanceGenerationMode genMode, boolean shouldSort) {
|
||||
getPosToGenerate(posToGenerate, LodUtil.REGION_DETAIL_LEVEL, 0, 0, playerBlockPosX, playerBlockPosZ,
|
||||
priority, genMode, shouldSort, true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A recursive method that fills the posToGenerate array with all levelPos that
|
||||
* need to be generated.
|
||||
* <p>
|
||||
* TODO why don't we return the posToGenerate, it would make this easier to
|
||||
* understand
|
||||
* FIXME This is.... absolute hell currently. Needs clean up.
|
||||
*/
|
||||
private void getPosToGenerate(PosToGenerateContainer posToGenerate, byte detailLevel, int offsetPosX, int offsetPosZ,
|
||||
int playerPosX, int playerPosZ, EGenerationPriority priority, EDistanceGenerationMode genMode, boolean shouldSort, boolean needFarPos) {
|
||||
// equivalent to 2^(...)
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
|
||||
// calculate what LevelPos are in range to generate
|
||||
double minDistance = LevelPosUtil.minDistance(detailLevel, offsetPosX + regionPosX*size, offsetPosZ + regionPosZ*size, playerPosX, playerPosZ);
|
||||
|
||||
// determine this child's levelPos
|
||||
byte childDetailLevel = (byte) (detailLevel - 1);
|
||||
int childOffsetPosX = offsetPosX * 2;
|
||||
int childOffsetPosZ = offsetPosZ * 2;
|
||||
EDistanceGenerationMode testerGenMode = genMode;//detailLevel >= LodUtil.CHUNK_DETAIL_LEVEL ? DistanceGenerationMode.NONE : genMode;
|
||||
|
||||
byte targetDetailLevel = DetailDistanceUtil.getDetailLevelFromDistance(minDistance);
|
||||
int farModeSwitchLevel = (priority == EGenerationPriority.NEAR_FIRST) ? -1 : calculateFarModeSwitch(targetDetailLevel);
|
||||
if (priority == EGenerationPriority.FAR_FIRST) farModeSwitchLevel = 8;
|
||||
boolean doesDataExist = doesDataExist(detailLevel, offsetPosX + regionPosX * size, offsetPosZ + regionPosZ * size, testerGenMode);
|
||||
|
||||
boolean isFarModeSwitchEdge = needFarPos && detailLevel <= farModeSwitchLevel;
|
||||
if (isFarModeSwitchEdge) needFarPos = false;
|
||||
|
||||
if (targetDetailLevel >= detailLevel) {
|
||||
if (!doesDataExist) {
|
||||
if (isFarModeSwitchEdge)
|
||||
posToGenerate.addFarPosToGenerate(detailLevel, offsetPosX + regionPosX * size,
|
||||
offsetPosZ + regionPosZ * size, shouldSort);
|
||||
else
|
||||
posToGenerate.addNearPosToGenerate(detailLevel, offsetPosX + regionPosX * size,
|
||||
offsetPosZ + regionPosZ * size, shouldSort);
|
||||
}
|
||||
} else if (!doesDataExist && isFarModeSwitchEdge) {
|
||||
posToGenerate.addFarPosToGenerate(detailLevel, offsetPosX + regionPosX * size,
|
||||
offsetPosZ + regionPosZ * size, shouldSort);
|
||||
} else if (detailLevel > LodUtil.CHUNK_DETAIL_LEVEL) {
|
||||
for (int x = 0; x <= 1; x++)
|
||||
for (int z = 0; z <= 1; z++)
|
||||
getPosToGenerate(posToGenerate, childDetailLevel, childOffsetPosX + x, childOffsetPosZ + z, playerPosX,
|
||||
playerPosZ, priority, genMode, shouldSort, needFarPos);
|
||||
} else {
|
||||
getPosToGenerate(posToGenerate, childDetailLevel, childOffsetPosX, childOffsetPosZ, playerPosX, playerPosZ,
|
||||
priority, genMode, shouldSort, needFarPos);
|
||||
}
|
||||
}
|
||||
|
||||
public byte getRenderDetailLevelAt(int playerPosX, int playerPosZ, byte detailLevel, int offsetX, int offsetZ) {
|
||||
EGenerationPriority generationPriority = getResolvedGenerationPriority();
|
||||
EDropoffQuality dropoffQuality = CONFIG.client().graphics().quality().getResolvedDropoffQuality();
|
||||
|
||||
double minDistance = LevelPosUtil.minDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ,
|
||||
playerPosX, playerPosZ);
|
||||
byte targetLevel = DetailDistanceUtil.getDetailLevelFromDistance(minDistance);
|
||||
byte renderLevel;
|
||||
if (targetLevel > dropoffQuality.fastModeSwitch) {
|
||||
double centerDistance = LevelPosUtil.centerDistance(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ, playerPosX, playerPosZ);
|
||||
renderLevel = DetailDistanceUtil.getDetailLevelFromDistance(centerDistance);
|
||||
} else {
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
double posMinDistance = LevelPosUtil.minDistance(detailLevel,
|
||||
LevelPosUtil.getRegionModule(detailLevel, offsetX) + regionPosX*size,
|
||||
LevelPosUtil.getRegionModule(detailLevel, offsetZ) + regionPosZ*size,
|
||||
playerPosX, playerPosZ);
|
||||
renderLevel = DetailDistanceUtil.getDetailLevelFromDistance(posMinDistance);
|
||||
}
|
||||
return (byte) Math.max(getMinDetailLevel(), renderLevel);
|
||||
}
|
||||
|
||||
|
||||
private EGenerationPriority getResolvedGenerationPriority() {
|
||||
EGenerationPriority priority = Config.Client.WorldGenerator.generationPriority.get();
|
||||
IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
if (priority == EGenerationPriority.AUTO)
|
||||
priority = MC.hasSinglePlayerServer() ? EGenerationPriority.FAR_FIRST : EGenerationPriority.BALANCED;
|
||||
return priority;
|
||||
}
|
||||
|
||||
private EDropoffQuality getResolvedDropoffQuality() {
|
||||
EDropoffQuality dropoffQuality = Config.Client.Graphics.Quality.dropoffQuality.get();
|
||||
if (dropoffQuality == EDropoffQuality.AUTO)
|
||||
dropoffQuality = Config.Client.Graphics.Quality.lodChunkRenderDistance.get() < 128 ?
|
||||
EDropoffQuality.SMOOTH_DROPOFF : EDropoffQuality.PERFORMANCE_FOCUSED;
|
||||
return dropoffQuality;
|
||||
}
|
||||
|
||||
|
||||
public static final class LevelPos {
|
||||
public final byte detail;
|
||||
public final int posX;
|
||||
public final int posZ;
|
||||
LevelPos(byte d, int x, int z) {
|
||||
detail = d;
|
||||
posX = x;
|
||||
posZ = z;
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<LevelPos> posToRenderIterator() {
|
||||
return new Iterator<LevelPos>() {
|
||||
final byte minDetail = minDetailLevel;
|
||||
int offsetX = 0;
|
||||
int offsetZ = 0;
|
||||
final int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - minDetail);
|
||||
|
||||
private void advance() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
|
||||
|
||||
return (offsetZ >= size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelPos next()
|
||||
{
|
||||
|
||||
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates all children.
|
||||
* <p>
|
||||
* TODO could this be renamed mergeArea?
|
||||
*/
|
||||
public void updateArea(byte detailLevel, int posX, int posZ) {
|
||||
int width;
|
||||
int startX;
|
||||
int startZ;
|
||||
|
||||
// Update the level lower or equal to the detail level
|
||||
for (byte down = (byte) (minDetailLevel + 1); down <= detailLevel; down++) {
|
||||
startX = LevelPosUtil.convert(detailLevel, posX, down);
|
||||
startZ = LevelPosUtil.convert(detailLevel, posZ, down);
|
||||
width = 1 << (detailLevel - down);
|
||||
|
||||
for (int x = 0; x < width; x++)
|
||||
for (int z = 0; z < width; z++)
|
||||
update(down, startX + x, startZ + z);
|
||||
}
|
||||
|
||||
// Update the level higher than the detail level
|
||||
for (byte up = (byte) (Math.max(detailLevel, minDetailLevel) + 1); up <= LodUtil.REGION_DETAIL_LEVEL; up++) {
|
||||
update(up, LevelPosUtil.convert(detailLevel, posX, up), LevelPosUtil.convert(detailLevel, posZ, up));
|
||||
}
|
||||
needSignalToRegenBuffer = true;
|
||||
}
|
||||
|
||||
public boolean regenerateLodFromArea(byte detailLevel, int posX, int posZ, int widthX, int widthZ) {
|
||||
if (detailLevel >= LodUtil.REGION_DETAIL_LEVEL) return false;
|
||||
int modPosX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
int modPosZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
//ApiShared.LOGGER.info("RegenerateLodFromArea(region:{} level:{}, x:{}, z:{}, wx:{}, wz:{})",
|
||||
// getRegionPos(), detailLevel, modPosX, modPosZ, widthX, widthZ);
|
||||
if (detailLevel < minDetailLevel) {
|
||||
byte startLevel = minDetailLevel;
|
||||
int maxPosX = Math.floorDiv(modPosX+widthX-1, (1 << (minDetailLevel-startLevel)))+1;
|
||||
int maxPosZ = Math.floorDiv(modPosZ+widthZ-1, (1 << (minDetailLevel-startLevel)))+1;
|
||||
modPosX = Math.floorDiv(modPosX, (1 << (minDetailLevel-startLevel)));
|
||||
modPosZ = Math.floorDiv(modPosZ, (1 << (minDetailLevel-startLevel)));
|
||||
widthX = maxPosX-modPosX;
|
||||
widthZ = maxPosZ-modPosZ;
|
||||
detailLevel = minDetailLevel;
|
||||
}
|
||||
do {
|
||||
int maxPosX = Math.floorDiv(modPosX+widthX-1, 2)+1;
|
||||
int maxPosZ = Math.floorDiv(modPosZ+widthZ-1, 2)+1;
|
||||
modPosX = Math.floorDiv(modPosX, 2);
|
||||
modPosZ = Math.floorDiv(modPosZ, 2);
|
||||
widthX = maxPosX-modPosX;
|
||||
widthZ = maxPosZ-modPosZ;
|
||||
detailLevel++;
|
||||
// ApiShared.LOGGER.info(" - Shink: (level:{}, x:{}, z:{}, wx:{}, wz:{})", detailLevel, modPosX, modPosZ, widthX, widthZ);
|
||||
chunkUpdate(detailLevel, modPosX, modPosZ, widthX, widthZ);
|
||||
} while (detailLevel < LodUtil.REGION_DETAIL_LEVEL);
|
||||
|
||||
needSignalToRegenBuffer = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the child at the given relative Pos
|
||||
* <p>
|
||||
* TODO could this be renamed mergeChildData?
|
||||
* TODO make this return whether any value has changed
|
||||
*/
|
||||
private void update(byte detailLevel, int modPosX, int modPosZ) {
|
||||
//ApiShared.LOGGER.info(" - Update: (level:{}, subLevel:{}, mx:{}, mz:{})", detailLevel, detailLevel-1, modPosX, modPosZ);
|
||||
dataContainer[detailLevel].updateData(dataContainer[detailLevel - 1], modPosX, modPosZ);
|
||||
}
|
||||
private void chunkUpdate(byte detailLevel, int modPosX, int modPosZ, int widthX,int widthZ) {
|
||||
for (int ox=0; ox<widthX; ox++) {
|
||||
for (int oz=0; oz<widthZ; oz++) {
|
||||
update(detailLevel, modPosX+ox, modPosZ+oz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if data exists at the given relative Pos.
|
||||
*/
|
||||
public boolean doesDataExist(byte detailLevel, int posX, int posZ, EDistanceGenerationMode requiredMode) {
|
||||
if (detailLevel < minDetailLevel || dataContainer[detailLevel] == null)
|
||||
return false;
|
||||
|
||||
int modPosX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
int modPosZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
if (!dataContainer[detailLevel].doesItExist(modPosX, modPosZ)) return false;
|
||||
if (requiredMode== EDistanceGenerationMode.NONE) return true;
|
||||
byte mode = getGenerationMode(detailLevel, posX, posZ);
|
||||
return (mode>=requiredMode.complexity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the generation mode for the data point at the given relative pos.
|
||||
*/
|
||||
public byte getGenerationMode(byte detailLevel, int posX, int posZ) {
|
||||
|
||||
int modPosX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
int modPosZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
if (dataContainer[detailLevel] != null && dataContainer[detailLevel].doesItExist(modPosX, modPosZ))
|
||||
// We take the bottom information always
|
||||
// TODO what does that mean? bottom of what?
|
||||
return DataPointUtil.getGenerationMode(dataContainer[detailLevel].getSingleData(modPosX, modPosZ));
|
||||
else
|
||||
throw new RuntimeException("Data does not exist!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lowest (least detailed) detail level in this region
|
||||
*/
|
||||
public byte getMinDetailLevel() {
|
||||
return minDetailLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the LevelContainer for the detailLevel
|
||||
*
|
||||
* @throws IllegalArgumentException if the detailLevel is less than
|
||||
* minDetailLevel
|
||||
*/
|
||||
public LevelContainer getLevel(byte detailLevel) {
|
||||
if (detailLevel < minDetailLevel)
|
||||
throw new IllegalArgumentException("getLevel asked for a detail level that does not exist: minimum: ["
|
||||
+ minDetailLevel + "] level requested: [" + detailLevel + "]");
|
||||
|
||||
return dataContainer[detailLevel];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the levelContainer to this Region, updating the minDetailLevel if
|
||||
* necessary.
|
||||
*
|
||||
* @throws IllegalArgumentException if the LevelContainer's detailLevel is 2 or
|
||||
* more detail levels lower than the
|
||||
* minDetailLevel of this region.
|
||||
*/
|
||||
public void addLevelContainer(LevelContainer levelContainer) {
|
||||
if (levelContainer.getDetailLevel() < minDetailLevel - 1) {
|
||||
throw new IllegalArgumentException("the LevelContainer's detailLevel was " + "["
|
||||
+ levelContainer.getDetailLevel() + "] but this region "
|
||||
+ "only allows adding LevelContainers with a " + "detail level of [" + (minDetailLevel - 1) + "]");
|
||||
}
|
||||
|
||||
dataContainer[levelContainer.getDetailLevel()] = levelContainer;
|
||||
if (levelContainer.getDetailLevel() == minDetailLevel - 1)
|
||||
minDetailLevel = levelContainer.getDetailLevel();
|
||||
|
||||
needRecheckGenPoint = true;
|
||||
}
|
||||
|
||||
// TODO James thinks cutTree and growTree (which he renamed to match cutTree)
|
||||
// should have more descriptive names, to make sure the "Tree" portion isn't
|
||||
// confused with Minecraft trees (the plant).
|
||||
|
||||
/**
|
||||
* Removes any dataContainers that are higher than the given detailLevel
|
||||
*/
|
||||
public void cutTree(byte detailLevel) {
|
||||
if (detailLevel > minDetailLevel) {
|
||||
minDetailLevel = detailLevel;
|
||||
for (byte detailLevelIndex = 0; detailLevelIndex < detailLevel; detailLevelIndex++)
|
||||
dataContainer[detailLevelIndex] = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this region more detailed to the detailLevel given. TODO is that
|
||||
* correct?
|
||||
*/
|
||||
public void growTree(byte detailLevel) {
|
||||
if (detailLevel < minDetailLevel) {
|
||||
for (byte detailLevelIndex = (byte) (minDetailLevel
|
||||
- 1); detailLevelIndex >= detailLevel; detailLevelIndex--) {
|
||||
if (dataContainer[detailLevelIndex + 1] == null)
|
||||
dataContainer[detailLevelIndex + 1] = new VerticalLevelContainer((byte) (detailLevelIndex + 1));
|
||||
|
||||
dataContainer[detailLevelIndex] = dataContainer[detailLevelIndex + 1].expand();
|
||||
}
|
||||
minDetailLevel = detailLevel;
|
||||
needRecheckGenPoint = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return RegionPos of this lod region
|
||||
*/
|
||||
public DHRegionPos getRegionPos() {
|
||||
return new DHRegionPos(regionPosX, regionPosZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many LODs are in this region
|
||||
*/
|
||||
public int getNumberOfLods() {
|
||||
int count = 0;
|
||||
for (LevelContainer container : dataContainer)
|
||||
count += container.getMaxNumberOfLods();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public EVerticalQuality getVerticalQuality() {
|
||||
return verticalQuality;
|
||||
}
|
||||
|
||||
public int getMaxVerticalData(byte detailLevel) {
|
||||
return dataContainer[detailLevel].getVerticalSize();
|
||||
}
|
||||
|
||||
public LevelContainer[] debugGetDataContainers() {return dataContainer;}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getLevel(LodUtil.REGION_DETAIL_LEVEL).toString();
|
||||
}
|
||||
}
|
||||
@@ -1,467 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects.lod;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.lod.core.objects.LodDataView;
|
||||
import com.seibel.lod.core.util.*;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version ??
|
||||
*/
|
||||
public class VerticalLevelContainer implements LevelContainer
|
||||
{
|
||||
public static final boolean DO_SAFETY_CHECKS = true;
|
||||
|
||||
private final short minHeight;
|
||||
public final byte detailLevel;
|
||||
public final int size;
|
||||
public final int verticalSize;
|
||||
|
||||
public final long[] dataContainer;
|
||||
|
||||
//Currently, these variable are not used. We are going to use them in the new data format
|
||||
public final int[] verticalDataContainer = null;
|
||||
public final int[] colorDataContainer = null;
|
||||
public final byte[] lightDataContainer = null;
|
||||
public final short[] positionDataContainer = null;
|
||||
|
||||
/*WE PROBABLY ARE GOING TO USE THIS IN THE FUTURE
|
||||
FOR NOW WE KEEP THE OLD SYSTEM
|
||||
public final short[] sectionVerticalSize = null;
|
||||
public final int[][] verticalDataContainer = null;
|
||||
public final int[][] colorDataContainer = null;
|
||||
public final byte[][] lightDataContainer = null;
|
||||
public final short[] positionDataContainer = null;
|
||||
*/
|
||||
|
||||
public VerticalLevelContainer(byte detailLevel)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
verticalSize = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
dataContainer = new long[size * size * DetailDistanceUtil.getMaxVerticalData(detailLevel)];
|
||||
minHeight = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte getDetailLevel()
|
||||
{
|
||||
return detailLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(int posX, int posZ)
|
||||
{
|
||||
for (int verticalIndex = 0; verticalIndex < verticalSize; verticalIndex++)
|
||||
dataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex] = DataPointUtil.EMPTY_DATA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addData(long data, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
dataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex] = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void forceWriteVerticalData(long[] data, int posX, int posZ)
|
||||
{
|
||||
int index = posX * size * verticalSize + posZ * verticalSize;
|
||||
if (verticalSize >= 0) System.arraycopy(data, 0, dataContainer, index + 0, verticalSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
forceWriteVerticalData(data, posX, posZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyVerticalData(LodDataView data, int posX, int posZ, boolean override) {
|
||||
if (DO_SAFETY_CHECKS) {
|
||||
if (data.size() != verticalSize)
|
||||
throw new IllegalArgumentException("data size not the same as vertical size");
|
||||
if (posX < 0 || posX >= size)
|
||||
throw new IllegalArgumentException("X position is out of bounds");
|
||||
if (posZ < 0 || posZ >= size)
|
||||
throw new IllegalArgumentException("Z position is out of bounds");
|
||||
}
|
||||
int index = posX * size * verticalSize + posZ * verticalSize;
|
||||
int compare = DataPointUtil.compareDatapointPriority(data.get(0), dataContainer[index]);
|
||||
if (override) {
|
||||
if (compare<0) return false;
|
||||
} else {
|
||||
if (compare<=0) return false;
|
||||
}
|
||||
data.copyTo(dataContainer, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addChunkOfData(long[] data, int posX, int posZ, int widthX, int widthZ, boolean override)
|
||||
{
|
||||
boolean anyChange = false;
|
||||
if (posX+widthX > size || posZ+widthZ > size)
|
||||
throw new IndexOutOfBoundsException("addChunkOfData param not inside valid range");
|
||||
if (widthX*widthZ*verticalSize != data.length)
|
||||
throw new IndexOutOfBoundsException("addChunkOfData data array not sized correctly to contain the data to be copied");
|
||||
if (posX<0 || posZ<0 || widthX<0 || widthZ<0)
|
||||
throw new IndexOutOfBoundsException("addChunkOfData param is negative");
|
||||
|
||||
for (int ox=0; ox<widthX; ox++) {
|
||||
anyChange = DataPointUtil.mergeTwoDataArray(
|
||||
dataContainer, ((ox+posX)*size+posZ) * verticalSize,
|
||||
data, ox*widthX*verticalSize,
|
||||
widthZ, verticalSize, override);
|
||||
}
|
||||
return anyChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean copyChunkOfData(LodDataView data, int posX, int posZ, int widthX, int widthZ, boolean override) {
|
||||
boolean anyChange = false;
|
||||
if (posX+widthX > size || posZ+widthZ > size)
|
||||
throw new IndexOutOfBoundsException("addChunkOfData param not inside valid range");
|
||||
if (widthX*widthZ*verticalSize != data.size())
|
||||
throw new IndexOutOfBoundsException("addChunkOfData data array not sized correctly to contain the data to be copied");
|
||||
if (posX<0 || posZ<0 || widthX<0 || widthZ<0)
|
||||
throw new IndexOutOfBoundsException("addChunkOfData param is negative");
|
||||
|
||||
for (int ox=0; ox<widthX; ox++) {
|
||||
anyChange |= new LodDataView(dataContainer, widthX*verticalSize,
|
||||
((ox+posX)*size+posZ) * verticalSize)
|
||||
.mergeWith(data, verticalSize, override);
|
||||
}
|
||||
return anyChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getData(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return dataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex];
|
||||
}
|
||||
|
||||
|
||||
public short getPositionData(int posX, int posZ)
|
||||
{
|
||||
return positionDataContainer[posX * size + posZ];
|
||||
}
|
||||
|
||||
public int getVerticalData(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return verticalDataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex];
|
||||
}
|
||||
|
||||
public int getColorData(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return colorDataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex];
|
||||
}
|
||||
|
||||
public byte getLightData(int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
return lightDataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex];
|
||||
}
|
||||
|
||||
public void setPositionData(short positionData, int posX, int posZ)
|
||||
{
|
||||
positionDataContainer[posX * size + posZ] = positionData;
|
||||
}
|
||||
|
||||
public void setVerticalData(int verticalData, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
verticalDataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex] = verticalData;
|
||||
}
|
||||
|
||||
public void setColorData(int colorData, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
colorDataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex] = colorData;
|
||||
}
|
||||
|
||||
public void setLightData(byte lightData, int posX, int posZ, int verticalIndex)
|
||||
{
|
||||
lightDataContainer[posX * size * verticalSize + posZ * verticalSize + verticalIndex] = lightData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSingleData(int posX, int posZ)
|
||||
{
|
||||
return dataContainer[posX * size * verticalSize + posZ * verticalSize];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getAllData(int posX, int posZ)
|
||||
{
|
||||
long[] result = new long[verticalSize];
|
||||
int index = posX * size * verticalSize + posZ * verticalSize;
|
||||
System.arraycopy(dataContainer, index, result, 0, verticalSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LodDataView getVerticalDataView(int posX, int posZ) {
|
||||
return new LodDataView(dataContainer, verticalSize, posX * size * verticalSize + posZ * verticalSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVerticalSize()
|
||||
{
|
||||
return verticalSize;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doesItExist(int posX, int posZ)
|
||||
{
|
||||
return DataPointUtil.doesItExist(getSingleData(posX, posZ));
|
||||
}
|
||||
|
||||
private long[] readDataVersion6(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = size * size * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
patchVersion9Reorder(result);
|
||||
patchHeightAndDepth(result,-minHeight);
|
||||
return result;
|
||||
}
|
||||
private long[] readDataVersion7(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = size * size * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
patchVersion9Reorder(result);
|
||||
patchHeightAndDepth(result, 64 - minHeight);
|
||||
return result;
|
||||
}
|
||||
|
||||
private long[] readDataVersion8(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = size * size * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
short tempMinHeight = Short.reverseBytes(inputData.readShort());
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
patchVersion9Reorder(result);
|
||||
if (tempMinHeight != minHeight) {
|
||||
patchHeightAndDepth(result,tempMinHeight - minHeight);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private long[] readDataVersion9(DataInputStream inputData, int tempMaxVerticalData) throws IOException {
|
||||
int x = size * size * tempMaxVerticalData;
|
||||
byte[] data = new byte[x * Long.BYTES];
|
||||
short tempMinHeight = Short.reverseBytes(inputData.readShort());
|
||||
ByteBuffer bb = ByteBuffer.wrap(data).order(ByteOrder.LITTLE_ENDIAN);
|
||||
inputData.readFully(data);
|
||||
long[] result = new long[x];
|
||||
bb.asLongBuffer().get(result);
|
||||
if (tempMinHeight != minHeight) {
|
||||
patchHeightAndDepth(result,tempMinHeight - minHeight);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void patchHeightAndDepth(long[] data, int offset) {
|
||||
for (int i=0; i<data.length; i++) {
|
||||
data[i] = DataPointUtil.shiftHeightAndDepth(data[i], (short)offset);
|
||||
}
|
||||
}
|
||||
|
||||
private static void patchVersion9Reorder(long[] data) {
|
||||
for (int i=0; i<data.length; i++) {
|
||||
data[i] = DataPointUtil.version9Reorder(data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public VerticalLevelContainer(DataInputStream inputData, int version, byte expectedDetailLevel) throws IOException {
|
||||
minHeight = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getWrappedClientWorld().getMinHeight();
|
||||
detailLevel = inputData.readByte();
|
||||
if (detailLevel != expectedDetailLevel)
|
||||
throw new IOException("Invalid Data: The expected detail level should be "+expectedDetailLevel+
|
||||
" but the data header say it's "+detailLevel);
|
||||
|
||||
size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
int fileMaxVerticalData = inputData.readByte() & 0b01111111;
|
||||
long[] tempDataContainer = null;
|
||||
|
||||
switch (version) {
|
||||
case 6:
|
||||
tempDataContainer = readDataVersion6(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
case 7:
|
||||
tempDataContainer = readDataVersion7(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
case 8:
|
||||
tempDataContainer = readDataVersion8(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
case 9:
|
||||
tempDataContainer = readDataVersion9(inputData, fileMaxVerticalData);
|
||||
break;
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
|
||||
int targetMaxVerticalData = DetailDistanceUtil.getMaxVerticalData(detailLevel);
|
||||
verticalSize = targetMaxVerticalData;
|
||||
dataContainer = DataPointUtil.changeMaxVertSize(tempDataContainer, fileMaxVerticalData, verticalSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LevelContainer expand()
|
||||
{
|
||||
return new VerticalLevelContainer((byte) (getDetailLevel() - 1));
|
||||
}
|
||||
|
||||
private static final ThreadLocal<long[][]> tLocalVerticalUpdateArrays = ThreadLocal.withInitial(() ->
|
||||
{
|
||||
return new long[LodUtil.DETAIL_OPTIONS - 1][];
|
||||
});
|
||||
|
||||
@Override
|
||||
public void updateData(LevelContainer lowerLevelContainer, int posX, int posZ)
|
||||
{
|
||||
//We reset the array
|
||||
long[][] verticalUpdateArrays = tLocalVerticalUpdateArrays.get();
|
||||
long[] dataToMerge = verticalUpdateArrays[detailLevel-1];
|
||||
int arrayLength = DetailDistanceUtil.getMaxVerticalData(detailLevel-1) * 4;
|
||||
if (dataToMerge == null || dataToMerge.length != arrayLength) {
|
||||
dataToMerge = new long[arrayLength];
|
||||
verticalUpdateArrays[detailLevel-1] = dataToMerge;
|
||||
} else Arrays.fill(dataToMerge, 0);
|
||||
|
||||
int lowerMaxVertical = dataToMerge.length / 4;
|
||||
int childPosX;
|
||||
int childPosZ;
|
||||
long[] data;
|
||||
boolean anyDataExist = false;
|
||||
for (int x = 0; x <= 1; x++)
|
||||
{
|
||||
for (int z = 0; z <= 1; z++)
|
||||
{
|
||||
childPosX = 2 * posX + x;
|
||||
childPosZ = 2 * posZ + z;
|
||||
if (lowerLevelContainer.doesItExist(childPosX, childPosZ)) anyDataExist = true;
|
||||
for (int verticalIndex = 0; verticalIndex < lowerMaxVertical; verticalIndex++)
|
||||
dataToMerge[(z * 2 + x) * lowerMaxVertical + verticalIndex] = lowerLevelContainer.getData(childPosX, childPosZ, verticalIndex);
|
||||
}
|
||||
}
|
||||
data = DataPointUtil.mergeMultiData(dataToMerge, lowerMaxVertical, getVerticalSize());
|
||||
if (!anyDataExist)
|
||||
throw new RuntimeException("Update data called but no child datapoint exist!");
|
||||
|
||||
if ((!DataPointUtil.doesItExist(data[0])) && anyDataExist)
|
||||
throw new RuntimeException("Update data called but higher level datapoint doesn't exist even though child data does exist!");
|
||||
|
||||
//FIXME: Disabled check if genMode for old data is already invalid due to having genMode 0.
|
||||
if (DataPointUtil.getGenerationMode(data[0]) != DataPointUtil.getGenerationMode(lowerLevelContainer.getSingleData(posX*2, posZ*2)))
|
||||
throw new RuntimeException("Update data called but higher level datapoint does not have the same GenerationMode as the top left corner child datapoint!");
|
||||
|
||||
forceWriteVerticalData(data, posX, posZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean writeData(DataOutputStream output) throws IOException {
|
||||
output.writeByte(detailLevel);
|
||||
output.writeByte((byte) verticalSize);
|
||||
output.writeByte((byte) (minHeight & 0xFF));
|
||||
output.writeByte((byte) ((minHeight >> 8) & 0xFF));
|
||||
boolean allGenerated = true;
|
||||
int x = size * size;
|
||||
for (int i = 0; i < x; i++)
|
||||
{
|
||||
for (int j = 0; j < verticalSize; j++)
|
||||
{
|
||||
long current = dataContainer[i * verticalSize + j];
|
||||
output.writeLong(Long.reverseBytes(current));
|
||||
}
|
||||
if (!DataPointUtil.doesItExist(dataContainer[i]))
|
||||
allGenerated = false;
|
||||
}
|
||||
return allGenerated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String LINE_DELIMITER = "\n";
|
||||
String DATA_DELIMITER = " ";
|
||||
String SUBDATA_DELIMITER = ",";
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
int size = 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel);
|
||||
stringBuilder.append(detailLevel);
|
||||
stringBuilder.append(LINE_DELIMITER);
|
||||
for (int z = 0; z < size; z++)
|
||||
{
|
||||
for (int x = 0; x < size; x++)
|
||||
{
|
||||
for (int y = 0; y < verticalSize; y++) {
|
||||
//Converting the dataToHex
|
||||
stringBuilder.append(Long.toHexString(getData(x,z,y)));
|
||||
if (y != verticalSize) stringBuilder.append(SUBDATA_DELIMITER);
|
||||
}
|
||||
if (x != size) stringBuilder.append(DATA_DELIMITER);
|
||||
}
|
||||
if (z != size) stringBuilder.append(LINE_DELIMITER);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxNumberOfLods()
|
||||
{
|
||||
return size * size * getVerticalSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRoughRamUsage()
|
||||
{
|
||||
return dataContainer.length * Long.BYTES;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects.opengl;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodQuadBuilder;
|
||||
import com.seibel.lod.core.enums.config.EGpuUploadMethod;
|
||||
import com.seibel.lod.core.render.LodRenderProgram;
|
||||
import com.seibel.lod.core.util.StatsMap;
|
||||
|
||||
public abstract class RenderBuffer implements AutoCloseable
|
||||
{
|
||||
|
||||
private enum State {
|
||||
None,
|
||||
Building,
|
||||
Uploading,
|
||||
Closed,
|
||||
}
|
||||
private State owner = State.None;
|
||||
private State nextOwner = State.None;
|
||||
final private void _lockThread(State newOwner) {
|
||||
if (owner != State.None || (nextOwner != State.None && nextOwner != newOwner))
|
||||
throw new ConcurrentModificationException("RenderMethod Illegal state!");
|
||||
owner = newOwner;
|
||||
nextOwner = State.None;
|
||||
}
|
||||
final private void _unlockThread(State oldOwner) {
|
||||
if (owner != oldOwner)
|
||||
throw new ConcurrentModificationException("RenderMethod Illegal state!");
|
||||
owner = State.None;
|
||||
}
|
||||
final private void _unlockThreadTo(State oldOwner, State newOwner) {
|
||||
if (owner != oldOwner)
|
||||
throw new ConcurrentModificationException("RenderMethod Illegal state!");
|
||||
owner = State.None;
|
||||
nextOwner = newOwner;
|
||||
}
|
||||
|
||||
final public void build(Runnable r) {
|
||||
_lockThread(State.Building);
|
||||
try {
|
||||
r.run();
|
||||
} finally {
|
||||
_unlockThread(State.Building);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return false if current renderMethod is not suited for current builder
|
||||
* This will auto close the object if returning false. */
|
||||
final public boolean tryUploadBuffers(LodQuadBuilder builder, EGpuUploadMethod uploadMethod) {
|
||||
_lockThread(State.Uploading);
|
||||
boolean successful = false;
|
||||
try {
|
||||
successful = uploadBuffers(builder, uploadMethod);
|
||||
return successful;
|
||||
} finally {
|
||||
if (!successful) {
|
||||
_unlockThreadTo(State.Uploading, State.Closed);
|
||||
close();
|
||||
} else {
|
||||
_unlockThread(State.Uploading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
// ====================== Methods for implementations ===================
|
||||
// ======================================================================
|
||||
|
||||
// =========== Called by build starter thread ==========
|
||||
|
||||
/* Called on being reused after the object is swapped to the back
|
||||
* and a new build event is triggered. Used for cleaning up non
|
||||
* reusable objects sooner.
|
||||
* Note: This is run on BUILDER thread, and does not have access to
|
||||
* GL Context, Use GLProxy.recordOpenGlCall() to access GL Context
|
||||
* instead! */
|
||||
public void onReuse() {}
|
||||
|
||||
// =========== Called by buffer upload thread ==========
|
||||
|
||||
/* Return false if current renderMethod is not suited for current builder
|
||||
* If false, close call will be automatically triggered.
|
||||
* If true, the object will be used (by first calling the swapBufferToFront())
|
||||
* on tick render. */
|
||||
protected abstract boolean uploadBuffers(LodQuadBuilder builder, EGpuUploadMethod uploadMethod);
|
||||
|
||||
// ========== Called by render thread ==========
|
||||
|
||||
/* Called on buffer first being used by a render thread. */
|
||||
public void onSwapToFront() {}
|
||||
|
||||
/* Called on buffer no longer being used. (Life ended)
|
||||
* Return false if current object cannot be reused.
|
||||
* Note: This should not do too much stuff as it is run on render thread!
|
||||
* The corresponding cleanups should be done using the onReuse() to prevent
|
||||
* lag spikes! If you want this buffer to not be reused, but cleanup is
|
||||
* expensive, use onReuse() instead!
|
||||
* Note 2: This may not be triggered on some situations like renderer being
|
||||
* terminated, or dimension changed. So implementation should NEVER assume
|
||||
* that onSwapToFront() will link to a call of onSwapToBack()! */
|
||||
public boolean onSwapToBack() {return true;}
|
||||
|
||||
/* Called on... well... rendering.
|
||||
* Return false if nothing rendered. (Optional) */
|
||||
public abstract boolean render(LodRenderProgram shaderProgram);
|
||||
|
||||
// ========== Called by any thread. (thread safe) ==========
|
||||
|
||||
/* Called by anyone. This method is allowed to throw exceptions, but
|
||||
* are never allowed to modify any values. This should behave the same
|
||||
* to other methods as if the method have never been called.
|
||||
* Note: This method is PURELY for debug or stats logging ONLY! */
|
||||
public abstract void debugDumpStats(StatsMap statsMap);
|
||||
|
||||
// ========= Called only when 1 thread is using it =======
|
||||
/* This method is called when object is no longer in use.
|
||||
* Called either after uploadBuffers() returned false (On buffer Upload
|
||||
* thread), or by others when the object is not being used. (not in build,
|
||||
* upload, or render state). */
|
||||
public abstract void close();
|
||||
|
||||
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ComsumerOutputStream extends OutputStream
|
||||
{
|
||||
final Consumer<String> func;
|
||||
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
public ComsumerOutputStream(Consumer<String> func) {
|
||||
this.func = func;
|
||||
}
|
||||
@Override
|
||||
public void write(int b)
|
||||
{
|
||||
buffer.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
buffer.write(b);
|
||||
}
|
||||
@Override
|
||||
public void write(byte[] b,
|
||||
int off,
|
||||
int len) {
|
||||
buffer.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush()
|
||||
{
|
||||
String str = buffer.toString();
|
||||
buffer.reset();
|
||||
func.accept(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
buffer.close();
|
||||
}
|
||||
}
|
||||
@@ -1,708 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
import com.seibel.lod.core.logging.SpamReducedLogger;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version ??
|
||||
*/
|
||||
public class DataPointUtil
|
||||
{
|
||||
/*
|
||||
|
||||
|_ |g |g |g |a |a |a |a |
|
||||
|r |r |r |r |r |r |r |r |
|
||||
|g |g |g |g |g |g |g |g |
|
||||
|b |b |b |b |b |b |b |b |
|
||||
|
||||
|h |h |h |h |h |h |h |h |
|
||||
|h |h |h |h |d |d |d |d |
|
||||
|d |d |d |d |d |d |d |d |
|
||||
|bl |bl |bl |bl |sl |sl |sl |sl |
|
||||
|
||||
*/
|
||||
|
||||
// Reminder: bytes have range of [-128, 127].
|
||||
// When converting to or from an int a 128 should be added or removed.
|
||||
// If there is a bug with color then it's probably caused by this.
|
||||
|
||||
public final static int EMPTY_DATA = 0;
|
||||
public final static int MAX_WORLD_Y_SIZE = 4096;
|
||||
|
||||
public final static int ALPHA_DOWNSIZE_SHIFT = 4;
|
||||
|
||||
|
||||
public final static int GEN_TYPE_SHIFT = 60;
|
||||
|
||||
public final static int COLOR_SHIFT = 32;
|
||||
public final static int BLUE_SHIFT = COLOR_SHIFT;
|
||||
public final static int GREEN_SHIFT = BLUE_SHIFT + 8;
|
||||
public final static int RED_SHIFT = GREEN_SHIFT + 8;
|
||||
public final static int ALPHA_SHIFT = RED_SHIFT + 8;
|
||||
|
||||
public final static int HEIGHT_SHIFT = 20;
|
||||
public final static int DEPTH_SHIFT = 8;
|
||||
public final static int BLOCK_LIGHT_SHIFT = 4;
|
||||
public final static int SKY_LIGHT_SHIFT = 0;
|
||||
|
||||
public final static long ALPHA_MASK = 0xF;
|
||||
public final static long RED_MASK = 0xFF;
|
||||
public final static long GREEN_MASK = 0xFF;
|
||||
public final static long BLUE_MASK = 0xFF;
|
||||
public final static long COLOR_MASK = 0xFFFFFF;
|
||||
public final static long HEIGHT_MASK = 0xFFF;
|
||||
public final static long DEPTH_MASK = 0xFFF;
|
||||
public final static long HEIGHT_DEPTH_MASK = 0xFFFFFF;
|
||||
public final static long BLOCK_LIGHT_MASK = 0xF;
|
||||
public final static long SKY_LIGHT_MASK = 0xF;
|
||||
public final static long GEN_TYPE_MASK = 0b111;
|
||||
public final static long COMPARE_SHIFT = GEN_TYPE_SHIFT;
|
||||
|
||||
public final static long HEIGHT_SHIFTED_MASK = HEIGHT_MASK << HEIGHT_SHIFT;
|
||||
public final static long DEPTH_SHIFTED_MASK = DEPTH_MASK << DEPTH_SHIFT;
|
||||
|
||||
public final static long VOID_SETTER = HEIGHT_SHIFTED_MASK | DEPTH_SHIFTED_MASK;
|
||||
|
||||
|
||||
public static long createVoidDataPoint(byte generationMode)
|
||||
{
|
||||
if (generationMode == 0)
|
||||
throw new IllegalArgumentException("Trying to create void datapoint with genMode 0, which is NOT allowed in DataPoint version 10!");
|
||||
return (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT;
|
||||
}
|
||||
|
||||
public static long createDataPoint(int height, int depth, int color, int lightSky, int lightBlock, int generationMode)
|
||||
{
|
||||
return createDataPoint(
|
||||
ColorUtil.getAlpha(color),
|
||||
ColorUtil.getRed(color),
|
||||
ColorUtil.getGreen(color),
|
||||
ColorUtil.getBlue(color),
|
||||
height, depth, lightSky, lightBlock, generationMode);
|
||||
}
|
||||
|
||||
public static long createDataPoint(int alpha, int red, int green, int blue, int height, int depth, int lightSky, int lightBlock, int generationMode)
|
||||
{
|
||||
if (generationMode == 0)
|
||||
throw new IllegalArgumentException("Trying to create datapoint with genMode 0, which is NOT allowed in DataPoint version 10!");
|
||||
if (height < 0 || height > 4096)
|
||||
throw new IllegalArgumentException("Height must be between 0 and 4096!");
|
||||
if (depth < 0 || depth > 4096)
|
||||
throw new IllegalArgumentException("Depth must be between 0 and 4096!");
|
||||
if (lightSky < 0 || lightSky > 15)
|
||||
throw new IllegalArgumentException("Sky light must be between 0 and 15!");
|
||||
if (lightBlock < 0 || lightBlock > 15)
|
||||
throw new IllegalArgumentException("Block light must be between 0 and 15!");
|
||||
if (alpha < 0 || alpha > 255)
|
||||
throw new IllegalArgumentException("Alpha must be between 0 and 255!");
|
||||
if (red < 0 || red > 255)
|
||||
throw new IllegalArgumentException("Red must be between 0 and 255!");
|
||||
if (green < 0 || green > 255)
|
||||
throw new IllegalArgumentException("Green must be between 0 and 255!");
|
||||
if (blue < 0 || blue > 255)
|
||||
throw new IllegalArgumentException("Blue must be between 0 and 255!");
|
||||
if (generationMode < 0 || generationMode > 7)
|
||||
throw new IllegalArgumentException("Generation mode must be between 0 and 7!");
|
||||
if (depth > height)
|
||||
throw new IllegalArgumentException("Depth must be less than or equal to height!");
|
||||
|
||||
return (long) (alpha >>> ALPHA_DOWNSIZE_SHIFT) << ALPHA_SHIFT
|
||||
| (red & RED_MASK) << RED_SHIFT
|
||||
| (green & GREEN_MASK) << GREEN_SHIFT
|
||||
| (blue & BLUE_MASK) << BLUE_SHIFT
|
||||
| (height & HEIGHT_MASK) << HEIGHT_SHIFT
|
||||
| (depth & DEPTH_MASK) << DEPTH_SHIFT
|
||||
| (lightBlock & BLOCK_LIGHT_MASK) << BLOCK_LIGHT_SHIFT
|
||||
| (lightSky & SKY_LIGHT_MASK) << SKY_LIGHT_SHIFT
|
||||
| (generationMode & GEN_TYPE_MASK) << GEN_TYPE_SHIFT
|
||||
;
|
||||
}
|
||||
|
||||
public static long shiftHeightAndDepth(long dataPoint, short offset) {
|
||||
long height = (dataPoint + ((long) offset << HEIGHT_SHIFT)) & HEIGHT_SHIFTED_MASK;
|
||||
long depth = (dataPoint + (offset << DEPTH_SHIFT)) & DEPTH_SHIFTED_MASK;
|
||||
return dataPoint & ~(HEIGHT_SHIFTED_MASK | DEPTH_SHIFTED_MASK) | height | depth;
|
||||
}
|
||||
|
||||
public static long version9Reorder(long dataPoint) {
|
||||
/*
|
||||
|a |a |a |a |r |r |r |r |
|
||||
|r |r |r |r |g |g |g |g |
|
||||
|g |g |g |g |b |b |b |b |
|
||||
|b |b |b |b |h |h |h |h |
|
||||
|h |h |h |h |h |h |d |d |
|
||||
|d |d |d |d |d |d |d |d |
|
||||
|bl |bl |bl |bl |sl |sl |sl |sl |
|
||||
|l |l |f |g |g |g |v |e |
|
||||
*/
|
||||
if ((dataPoint & 1) == 0) return 0;
|
||||
|
||||
long height = (dataPoint >>> 26) & 0x3FF;
|
||||
long depth = (dataPoint >>> 16) & 0x3FF;
|
||||
if (height == depth || (dataPoint & 0b10)==0b10) {
|
||||
return createVoidDataPoint((byte) (((dataPoint >>> 2) & 0b111) + 1));
|
||||
}
|
||||
return ((dataPoint >>> 60) & 0xF) << ALPHA_SHIFT
|
||||
| ((dataPoint >>> 52) & 0xFF) << RED_SHIFT
|
||||
| ((dataPoint >>> 44) & 0xFF) << GREEN_SHIFT
|
||||
| ((dataPoint >>> 36) & 0xFF) << BLUE_SHIFT
|
||||
| ((dataPoint >>> 26) & 0x3FF) << HEIGHT_SHIFT
|
||||
| ((dataPoint >>> 16) & 0x3FF) << DEPTH_SHIFT
|
||||
| ((dataPoint >>> 8) & 0xFF) << SKY_LIGHT_SHIFT
|
||||
| (((dataPoint >>> 2) & 0xFF) + 1) << GEN_TYPE_SHIFT;
|
||||
}
|
||||
|
||||
public static short getHeight(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK);
|
||||
}
|
||||
|
||||
public static short getDepth(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK);
|
||||
}
|
||||
|
||||
public static short getAlpha(long dataPoint)
|
||||
{
|
||||
return (short) ((((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT) | 0b1111);
|
||||
}
|
||||
|
||||
public static short getRed(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> RED_SHIFT) & RED_MASK);
|
||||
}
|
||||
|
||||
public static short getGreen(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> GREEN_SHIFT) & GREEN_MASK);
|
||||
}
|
||||
|
||||
public static short getBlue(long dataPoint)
|
||||
{
|
||||
return (short) ((dataPoint >>> BLUE_SHIFT) & BLUE_MASK);
|
||||
}
|
||||
|
||||
public static byte getLightSky(long dataPoint)
|
||||
{
|
||||
return (byte) ((dataPoint >>> SKY_LIGHT_SHIFT) & SKY_LIGHT_MASK);
|
||||
}
|
||||
|
||||
public static byte getLightBlock(long dataPoint)
|
||||
{
|
||||
return (byte) ((dataPoint >>> BLOCK_LIGHT_SHIFT) & BLOCK_LIGHT_MASK);
|
||||
}
|
||||
|
||||
|
||||
private static final SpamReducedLogger warnLogger = new SpamReducedLogger(1);
|
||||
|
||||
public static byte getGenerationMode(long dataPoint)
|
||||
{
|
||||
byte genMode = (byte) ((dataPoint >>> GEN_TYPE_SHIFT) & GEN_TYPE_MASK);
|
||||
if (warnLogger.canMaybeLog() && doesItExist(dataPoint) && genMode==0) {
|
||||
warnLogger.warnInc("Existing datapoint with genMode 0 detected! This is invalid in DataPoint version 10!"
|
||||
+ " This may be caused by old data that has not been updated correctly.");
|
||||
return 1;
|
||||
}
|
||||
return genMode == 0 ? 1 : genMode;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isVoid(long dataPoint)
|
||||
{
|
||||
return (((dataPoint >>> DEPTH_SHIFT) & HEIGHT_DEPTH_MASK) == 0);
|
||||
}
|
||||
|
||||
public static boolean doesItExist(long dataPoint)
|
||||
{
|
||||
return dataPoint!=0;
|
||||
}
|
||||
|
||||
public static int getColor(long dataPoint)
|
||||
{
|
||||
long alpha = getAlpha(dataPoint);
|
||||
return (int) (((dataPoint >>> COLOR_SHIFT) & COLOR_MASK) | (alpha << (ALPHA_SHIFT-COLOR_SHIFT)));
|
||||
}
|
||||
|
||||
/** This is used to convert a dataPoint to string (useful for the print function) */
|
||||
@SuppressWarnings("unused")
|
||||
public static String toString(long dataPoint)
|
||||
{
|
||||
return getHeight(dataPoint) + " " +
|
||||
getDepth(dataPoint) + " " +
|
||||
getAlpha(dataPoint) + " " +
|
||||
getRed(dataPoint) + " " +
|
||||
getBlue(dataPoint) + " " +
|
||||
getGreen(dataPoint) + " " +
|
||||
getLightBlock(dataPoint) + " " +
|
||||
getLightSky(dataPoint) + " " +
|
||||
getGenerationMode(dataPoint) + " " +
|
||||
isVoid(dataPoint) + " " +
|
||||
doesItExist(dataPoint) + '\n';
|
||||
}
|
||||
|
||||
public static void shrinkArray(short[] array, int packetSize, int start, int length, int arraySize)
|
||||
{
|
||||
start *= packetSize;
|
||||
length *= packetSize;
|
||||
arraySize *= packetSize;
|
||||
//remove comment to not leave garbage at the end
|
||||
//array[start + packetSize + i] = 0;
|
||||
if (arraySize - start >= 0) System.arraycopy(array, start + length, array, start, arraySize - start);
|
||||
}
|
||||
|
||||
public static void extendArray(short[] array, int packetSize, int start, int length, int arraySize)
|
||||
{
|
||||
start *= packetSize;
|
||||
length *= packetSize;
|
||||
arraySize *= packetSize;
|
||||
for (int i = arraySize - start - 1; i >= 0; i--)
|
||||
{
|
||||
array[start + length + i] = array[start + i];
|
||||
array[start + i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return (>0) if dataA should replace dataB, (0) if equal, (<0) if dataB should replace dataA */
|
||||
public static int compareDatapointPriority(long dataA, long dataB) {
|
||||
return (int) ((dataA >> COMPARE_SHIFT) - (dataB >> COMPARE_SHIFT));
|
||||
}
|
||||
|
||||
// Merge the newData data into the target data by comparing the Datapoint Priority.
|
||||
// If target and newData are same priority, it will use the target one.
|
||||
// If target and newData size are different, it will copy up to the smallest one.
|
||||
// Return whether anything changed
|
||||
public static boolean mergeTwoDataArray(long[] target, long[] newData, int verticalDataSize) {
|
||||
boolean anyChange = false;
|
||||
for (int i=0; i<target.length&&i<newData.length; i+=verticalDataSize) {
|
||||
if (compareDatapointPriority(newData[i], target[i])>0) {
|
||||
anyChange = true;
|
||||
System.arraycopy(newData, i, target, i, verticalDataSize);
|
||||
}
|
||||
}
|
||||
return anyChange;
|
||||
}
|
||||
|
||||
// Same as above, but with args for buffer offset.
|
||||
// Return whether anything changed
|
||||
public static boolean mergeTwoDataArray(long[] target, int targetOffset, long[] newData, int newDataOffset, int dataLength, int verticalDataSize, boolean override) {
|
||||
if (targetOffset + verticalDataSize*dataLength>target.length)
|
||||
throw new ArrayIndexOutOfBoundsException("\"target\" array index out of bounds");
|
||||
if (newDataOffset + verticalDataSize*dataLength>newData.length)
|
||||
throw new ArrayIndexOutOfBoundsException("\"newData\" array index out of bounds");
|
||||
boolean anyChange = false;
|
||||
for (int o=0; o<(dataLength*verticalDataSize); o+=verticalDataSize) {
|
||||
if (override) {
|
||||
if (compareDatapointPriority(newData[o+newDataOffset], target[o+targetOffset])>=0) {
|
||||
anyChange = true;
|
||||
System.arraycopy(newData, o+newDataOffset, target, o+targetOffset, verticalDataSize);
|
||||
}
|
||||
} else {
|
||||
if (compareDatapointPriority(newData[o+newDataOffset], target[o+targetOffset])>0) {
|
||||
anyChange = true;
|
||||
System.arraycopy(newData, o+newDataOffset, target, o+targetOffset, verticalDataSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
return anyChange;
|
||||
}
|
||||
|
||||
// Extract a section of data from the 2D data array
|
||||
public static long[] extractDataArray(long[] source, int inWidth, int inHeight, int outX, int outY, int outWidth, int outHeight) {
|
||||
int dataSetSize = source.length/inWidth/inHeight;
|
||||
if (dataSetSize*inWidth*inHeight != source.length)
|
||||
throw new ArrayIndexOutOfBoundsException("\"source\" array invalid width and height");
|
||||
if (outWidth > inWidth || outX + outWidth > inWidth)
|
||||
throw new ArrayIndexOutOfBoundsException("X index out of bounds");
|
||||
if (outHeight > inHeight || outY + outHeight > inHeight)
|
||||
throw new ArrayIndexOutOfBoundsException("Y index out of bounds");
|
||||
long[] out = new long[dataSetSize*outWidth*outHeight];
|
||||
for (int x=0; x<outWidth; x++) {
|
||||
System.arraycopy(source, ((outX+x)*inHeight+outY)*dataSetSize,
|
||||
out, (x*outHeight)*dataSetSize,
|
||||
outHeight*dataSetSize);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// Extract a section of data from the 2D data array
|
||||
// WARN: if sourceVertSize == targetVertSize, it will return the source array!!! Be careful about this!
|
||||
public static long[] changeMaxVertSize(long[] source, int sourceVertSize, int targetVertSize) {
|
||||
if (source.length%sourceVertSize != 0)
|
||||
throw new ArrayIndexOutOfBoundsException("\"source\" array invalid vertical size or length");
|
||||
if (sourceVertSize == targetVertSize) return source;
|
||||
if (sourceVertSize > targetVertSize) {
|
||||
int size = source.length/sourceVertSize;
|
||||
long[] dataToMerge = new long[sourceVertSize];
|
||||
long[] newData = new long[size * targetVertSize];
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
System.arraycopy(source, i * sourceVertSize, dataToMerge, 0, sourceVertSize);
|
||||
long[] tempBuffer = DataPointUtil.mergeMultiData(dataToMerge, sourceVertSize, targetVertSize);
|
||||
System.arraycopy(tempBuffer, 0, newData, i * targetVertSize, targetVertSize);
|
||||
}
|
||||
return newData;
|
||||
} else {
|
||||
int size = source.length/sourceVertSize;
|
||||
long[] newData = new long[size * targetVertSize];
|
||||
for (int i = 0; i < size; i++) {
|
||||
System.arraycopy(source, i * sourceVertSize, newData, i * targetVertSize, sourceVertSize);
|
||||
}
|
||||
return newData;
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadLocal<short[]> tLocalHeightAndDepth = new ThreadLocal<short[]>();
|
||||
private static final ThreadLocal<int[]> tDataIndexCache = new ThreadLocal<int[]>();
|
||||
private static final ThreadLocal<long[]> tMaxVerticalData = new ThreadLocal<long[]>();
|
||||
/**
|
||||
* This method merge column of multiple data together
|
||||
* @param dataToMerge one or more columns of data
|
||||
* @param inputVerticalData vertical size of an input data
|
||||
* @param maxVerticalData max vertical size of the merged data
|
||||
* @return one column of correctly parsed data
|
||||
*/
|
||||
// TODO: Make this operate on a out param array, to allow skipping copy array on use
|
||||
public static long[] mergeMultiData(long[] dataToMerge, int inputVerticalData, int maxVerticalData)
|
||||
{
|
||||
//size indicate how many position we are merging in one position
|
||||
int size = dataToMerge.length / inputVerticalData;
|
||||
|
||||
// We initialize the arrays that are going to be used
|
||||
int heightAndDepthLength = (MAX_WORLD_Y_SIZE / 2 + 16) * 2;
|
||||
short[] heightAndDepth = tLocalHeightAndDepth.get();
|
||||
if (heightAndDepth==null || heightAndDepth.length != heightAndDepthLength) {
|
||||
heightAndDepth = new short[heightAndDepthLength];
|
||||
tLocalHeightAndDepth.set(heightAndDepth);
|
||||
}
|
||||
int dataPointLength = maxVerticalData;
|
||||
long[] dataPoint = tMaxVerticalData.get();
|
||||
if (dataPoint==null || dataPoint.length != dataPointLength) {
|
||||
dataPoint = new long[dataPointLength];
|
||||
tMaxVerticalData.set(dataPoint);
|
||||
} else Arrays.fill(dataPoint, 0);
|
||||
|
||||
byte genMode = getGenerationMode(dataToMerge[0]);
|
||||
if (genMode == 0) genMode = 1; // FIXME: Hack to make the version 10 genMode never be 0.
|
||||
boolean allEmpty = true;
|
||||
boolean allVoid = true;
|
||||
boolean limited = false;
|
||||
boolean allDefault;
|
||||
long singleData;
|
||||
|
||||
|
||||
short depth;
|
||||
short height;
|
||||
int count = 0;
|
||||
int i;
|
||||
int ii;
|
||||
int dataIndex;
|
||||
|
||||
//We collect the indexes of the data, ordered by the depth
|
||||
for (int index = 0; index < size; index++)
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[dataIndex];
|
||||
if (doesItExist(singleData))
|
||||
{
|
||||
//genMode = Math.min(genMode, getGenerationMode(singleData));
|
||||
allEmpty = false;
|
||||
if (!isVoid(singleData))
|
||||
{
|
||||
allVoid = false;
|
||||
count++;
|
||||
heightAndDepth[dataIndex * 2] = getHeight(singleData);
|
||||
heightAndDepth[dataIndex * 2 +1] = getDepth(singleData);
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (dataIndex = 0; dataIndex < inputVerticalData; dataIndex++)
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData + dataIndex];
|
||||
if (doesItExist(singleData))
|
||||
{
|
||||
//genMode = Math.min(genMode, getGenerationMode(singleData));
|
||||
allEmpty = false;
|
||||
if (!isVoid(singleData))
|
||||
{
|
||||
allVoid = false;
|
||||
depth = getDepth(singleData);
|
||||
height = getHeight(singleData);
|
||||
|
||||
int botPos = -1;
|
||||
int topPos = -1;
|
||||
//values fall in between and possibly require extension of array
|
||||
boolean botExtend = false;
|
||||
boolean topExtend = false;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (depth < heightAndDepth[i * 2] && depth >= heightAndDepth[i * 2 + 1])
|
||||
{
|
||||
botPos = i;
|
||||
break;
|
||||
}
|
||||
else if (depth < heightAndDepth[i * 2 + 1] && ((i + 1 < count && depth >= heightAndDepth[(i + 1) * 2]) || i + 1 == count))
|
||||
{
|
||||
botPos = i;
|
||||
botExtend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
if (height <= heightAndDepth[i * 2] && height > heightAndDepth[i * 2 + 1])
|
||||
{
|
||||
topPos = i;
|
||||
break;
|
||||
}
|
||||
else if (height <= heightAndDepth[i * 2 + 1] && ((i + 1 < count && height > heightAndDepth[(i + 1) * 2]) || i + 1 == count))
|
||||
{
|
||||
topPos = i;
|
||||
topExtend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (topPos == -1)
|
||||
{
|
||||
if (botPos == -1)
|
||||
{
|
||||
//whole block falls above
|
||||
extendArray(heightAndDepth, 2, 0, 1, count);
|
||||
heightAndDepth[0] = height;
|
||||
heightAndDepth[1] = depth;
|
||||
count++;
|
||||
}
|
||||
else if (!botExtend)
|
||||
{
|
||||
//only top falls above extending it there, while bottom is inside existing
|
||||
shrinkArray(heightAndDepth, 2, 0, botPos, count);
|
||||
heightAndDepth[0] = height;
|
||||
count -= botPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
//top falls between some blocks, extending those as well
|
||||
shrinkArray(heightAndDepth, 2, 0, botPos, count);
|
||||
heightAndDepth[0] = height;
|
||||
heightAndDepth[1] = depth;
|
||||
count -= botPos;
|
||||
}
|
||||
}
|
||||
else if (!topExtend)
|
||||
{
|
||||
if (!botExtend)
|
||||
//both top and bottom are within some exiting blocks, possibly merging them
|
||||
heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1];
|
||||
else
|
||||
//top falls between some blocks, extending it there
|
||||
heightAndDepth[topPos * 2 + 1] = depth;
|
||||
shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!botExtend)
|
||||
{
|
||||
//only top is within some exiting block, extending it
|
||||
topPos++; //to make it easier
|
||||
heightAndDepth[topPos * 2] = height;
|
||||
heightAndDepth[topPos * 2 + 1] = heightAndDepth[botPos * 2 + 1];
|
||||
shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
//both top and bottom are outside existing blocks
|
||||
shrinkArray(heightAndDepth, 2, topPos + 1, botPos - topPos, count);
|
||||
count -= botPos - topPos;
|
||||
extendArray(heightAndDepth, 2, topPos + 1, 1, count);
|
||||
count++;
|
||||
heightAndDepth[topPos * 2 + 2] = height;
|
||||
heightAndDepth[topPos * 2 + 3] = depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//We check if there is any data that's not empty or void
|
||||
if (allEmpty)
|
||||
return dataPoint;
|
||||
if (allVoid)
|
||||
{
|
||||
dataPoint[0] = createVoidDataPoint(genMode);
|
||||
return dataPoint;
|
||||
}
|
||||
|
||||
//we limit the vertical portion to maxVerticalData
|
||||
int j = 0;
|
||||
while (count > maxVerticalData)
|
||||
{
|
||||
limited = true;
|
||||
ii = MAX_WORLD_Y_SIZE;
|
||||
for (i = 0; i < count - 1; i++)
|
||||
{
|
||||
if (heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2] <= ii)
|
||||
{
|
||||
ii = heightAndDepth[i * 2 + 1] - heightAndDepth[(i + 1) * 2];
|
||||
j = i;
|
||||
}
|
||||
}
|
||||
heightAndDepth[j * 2 + 1] = heightAndDepth[(j + 1) * 2 + 1];
|
||||
for (i = j + 1; i < count - 1; i++)
|
||||
{
|
||||
heightAndDepth[i * 2] = heightAndDepth[(i + 1) * 2];
|
||||
heightAndDepth[i * 2 + 1] = heightAndDepth[(i + 1) * 2 + 1];
|
||||
}
|
||||
//System.arraycopy(heightAndDepth, j + 1, heightAndDepth, j, count - j - 1);
|
||||
count--;
|
||||
}
|
||||
//As standard the vertical lods are ordered from top to bottom
|
||||
if (!limited && size == 1)
|
||||
{
|
||||
for (j = 0; j < count; j++)
|
||||
dataPoint[j] = dataToMerge[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
//We want to efficiently memorize indexes
|
||||
int[] dataIndexesCache = tDataIndexCache.get();
|
||||
if (dataIndexesCache==null || dataIndexesCache.length != size) {
|
||||
dataIndexesCache = new int[size];
|
||||
tDataIndexCache.set(dataIndexesCache);
|
||||
}
|
||||
Arrays.fill(dataIndexesCache,0);
|
||||
|
||||
//For each lod height-depth value we have found we now want to generate the rest of the data
|
||||
//by merging all lods at lower level that are contained inside the new ones
|
||||
for (j = 0; j < count; j++)
|
||||
{
|
||||
//We firstly collect height and depth data
|
||||
//this will be added to each realtive long DataPoint
|
||||
height = heightAndDepth[j * 2];
|
||||
depth = heightAndDepth[j * 2 + 1];
|
||||
|
||||
//if both height and depth are at 0 then we finished
|
||||
if ((depth == 0 && height == 0) || j >= heightAndDepth.length / 2)
|
||||
break;
|
||||
|
||||
//We initialize data useful for the merge
|
||||
int numberOfChildren = 0;
|
||||
allEmpty = true;
|
||||
allVoid = true;
|
||||
|
||||
//We initialize all the new values that we are going to put in the dataPoint
|
||||
int tempAlpha = 0;
|
||||
int tempRed = 0;
|
||||
int tempGreen = 0;
|
||||
int tempBlue = 0;
|
||||
int tempLightBlock = 0;
|
||||
int tempLightSky = 0;
|
||||
long data = 0;
|
||||
|
||||
//For each position that we want to merge
|
||||
for (int index = 0; index < size; index++)
|
||||
{
|
||||
//we scan the lods in the position from top to bottom
|
||||
while(dataIndexesCache[index] < inputVerticalData)
|
||||
{
|
||||
singleData = dataToMerge[index * inputVerticalData + dataIndexesCache[index]];
|
||||
if (doesItExist(singleData) && !isVoid(singleData))
|
||||
{
|
||||
dataIndexesCache[index]++;
|
||||
if ((depth <= getDepth(singleData) && getDepth(singleData) < height)
|
||||
|| (depth < getHeight(singleData) && getHeight(singleData) <= height))
|
||||
{
|
||||
data = singleData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (!doesItExist(data))
|
||||
{
|
||||
data = createVoidDataPoint(genMode);
|
||||
}
|
||||
|
||||
if (doesItExist(data))
|
||||
{
|
||||
allEmpty = false;
|
||||
if (!isVoid(data))
|
||||
{
|
||||
numberOfChildren++;
|
||||
allVoid = false;
|
||||
tempAlpha = Math.max(getAlpha(data),tempAlpha);
|
||||
tempRed += getRed(data) * getRed(data);
|
||||
tempGreen += getGreen(data) * getGreen(data);
|
||||
tempBlue += getBlue(data) * getBlue(data);
|
||||
tempLightBlock += getLightBlock(data);
|
||||
tempLightSky += getLightSky(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allEmpty)
|
||||
//no child has been initialized
|
||||
dataPoint[j] = EMPTY_DATA;
|
||||
else if (allVoid)
|
||||
//all the children are void
|
||||
dataPoint[j] = createVoidDataPoint(genMode);
|
||||
else
|
||||
{
|
||||
//we have at least 1 child
|
||||
if (size != 1)
|
||||
{
|
||||
tempRed = tempRed / numberOfChildren;
|
||||
tempGreen = tempGreen / numberOfChildren;
|
||||
tempBlue = tempBlue / numberOfChildren;
|
||||
tempLightBlock = tempLightBlock / numberOfChildren;
|
||||
tempLightSky = tempLightSky / numberOfChildren;
|
||||
}
|
||||
//data = createDataPoint(tempAlpha, tempRed, tempGreen, tempBlue, height, depth, tempLightSky, tempLightBlock, tempGenMode, allDefault);
|
||||
//if (j > 0 && getColor(data) == getColor(dataPoint[j]))
|
||||
//{
|
||||
// add simplification at the end due to color
|
||||
//}
|
||||
dataPoint[j] = createDataPoint(tempAlpha, (int) Math.sqrt(tempRed), (int) Math.sqrt(tempGreen), (int) Math.sqrt(tempBlue), height, depth, tempLightSky, tempLightBlock, genMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataPoint;
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import com.seibel.lod.core.enums.config.EHorizontalQuality;
|
||||
* @author Leonardo Amato
|
||||
* @version ??
|
||||
*/
|
||||
@Deprecated
|
||||
public class DetailDistanceUtil
|
||||
{
|
||||
private static byte minDetail = Config.Client.Graphics.Quality.drawResolution.get().detailLevel;
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public class EventLoop implements AutoCloseable { //FIXME This should have close. We are leaking stuff.
|
||||
public class EventLoop implements AutoCloseable {
|
||||
private final boolean PAUSE_ON_ERROR = ModInfo.IS_DEV_BUILD;
|
||||
private final Logger logger = DhLoggerBuilder.getLogger();
|
||||
private final ExecutorService executorService;
|
||||
|
||||
@@ -24,6 +24,7 @@ package com.seibel.lod.core.util;
|
||||
* @author Leonardo Amato
|
||||
* @version ??
|
||||
*/
|
||||
@Deprecated // Use DhSectionPos & DhLodPos & etc classes methods instead
|
||||
public class LevelPosUtil
|
||||
{
|
||||
public static int[] convert(int[] levelPos, byte newDetailLevel)
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.seibel.lod.core.a7.util.UncheckedInterruptedException;
|
||||
import com.seibel.lod.core.config.Config;
|
||||
import com.seibel.lod.core.enums.config.EServerFolderNameMode;
|
||||
import com.seibel.lod.core.enums.config.EVanillaOverdraw;
|
||||
@@ -33,7 +31,6 @@ import com.seibel.lod.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.objects.ParsedIp;
|
||||
import com.seibel.lod.core.objects.Pos2D;
|
||||
import com.seibel.lod.core.objects.DHRegionPos;
|
||||
import com.seibel.lod.core.objects.opengl.DefaultLodVertexFormats;
|
||||
import com.seibel.lod.core.objects.opengl.LodVertexFormat;
|
||||
import com.seibel.lod.core.util.gridList.EdgeDistanceBooleanGrid;
|
||||
@@ -41,9 +38,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.apache.logging.log4j.Level;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.message.Message;
|
||||
|
||||
/**
|
||||
* This class holds methods and constants that may be used in multiple places.
|
||||
@@ -183,15 +178,7 @@ public class LodUtil
|
||||
|
||||
return returnWorld;
|
||||
}
|
||||
|
||||
/** Convert a 2D absolute position into a quad tree relative position. */
|
||||
public static DHRegionPos convertGenericPosToRegionPos(int x, int z, int detailLevel)
|
||||
{
|
||||
int relativePosX = Math.floorDiv(x, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel));
|
||||
int relativePosZ = Math.floorDiv(z, 1 << (LodUtil.REGION_DETAIL_LEVEL - detailLevel));
|
||||
|
||||
return new DHRegionPos(relativePosX, relativePosZ);
|
||||
}
|
||||
|
||||
|
||||
/** returns the server name, IP and game version. */
|
||||
@Deprecated // FIXME: There are soooo many duplicated methods doing the same thing everywhere
|
||||
|
||||
@@ -1,304 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.util.gridList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/*Layout:
|
||||
* 0,1,2,
|
||||
* 3,4,5,
|
||||
* 6,7,8
|
||||
*/
|
||||
|
||||
@Deprecated // Replace with PosArrayGridList<T>
|
||||
public class MovableCenteredGridList<T> extends ArrayList<T> {
|
||||
|
||||
private int centerX;
|
||||
private int centerY;
|
||||
|
||||
public final int gridCentreToEdge;
|
||||
public final int gridSize;
|
||||
|
||||
/*
|
||||
* WARNING: Not yet tested if its atomic. (non Thread safe)
|
||||
*/
|
||||
public MovableCenteredGridList(MovableCenteredGridList<T> other) {
|
||||
super(other);
|
||||
centerX = other.centerX;
|
||||
centerY = other.centerY;
|
||||
gridCentreToEdge = other.gridCentreToEdge;
|
||||
gridSize = other.gridSize;
|
||||
}
|
||||
|
||||
public MovableCenteredGridList(int gridCentreToEdge, int centerX, int centerY) {
|
||||
super((gridCentreToEdge * 2 + 1) * (gridCentreToEdge * 2 + 1));
|
||||
gridSize = gridCentreToEdge * 2 + 1;
|
||||
this.gridCentreToEdge = gridCentreToEdge;
|
||||
this.centerX = centerX;
|
||||
this.centerY = centerY;
|
||||
clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
super.ensureCapacity(gridSize*gridSize);
|
||||
for (int i=0; i<gridSize*gridSize; i++) {
|
||||
super.add(null);
|
||||
}
|
||||
}
|
||||
public void clear(Consumer<? super T> d) {
|
||||
super.forEach((t) -> {
|
||||
if (t!=null) d.accept(t);
|
||||
});
|
||||
super.clear();
|
||||
super.ensureCapacity(gridSize*gridSize);
|
||||
for (int i=0; i<gridSize*gridSize; i++) {
|
||||
super.add(null);
|
||||
}
|
||||
}
|
||||
|
||||
public int getCenterX() {return centerX;}
|
||||
public int getCenterY() {return centerY;}
|
||||
|
||||
// return null if x,y is outside of the grid
|
||||
public T get(int x, int y) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return _getDirect(x,y);
|
||||
}
|
||||
|
||||
// return false if x,y is outside of the grid
|
||||
public boolean set(int x, int y, T t) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return _setDirect(x,y, t);
|
||||
}
|
||||
|
||||
// return null if x,y is outside of the grid
|
||||
// Otherwise, return the new value (for chaining)
|
||||
public T setAndGet(int x, int y, T t) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return _setDirect(x,y, t) ? t : null;
|
||||
}
|
||||
// return null if x,y is outside of the grid
|
||||
// Otherwise, return the old value
|
||||
public T swap(int x, int y, T t) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return _swapDirect(x,y, t);
|
||||
}
|
||||
|
||||
public boolean inRange(int x, int y) {
|
||||
x = x-centerX+gridCentreToEdge;
|
||||
y = y-centerY+gridCentreToEdge;
|
||||
return (x>=0 && x<gridSize && y>=0 && y<gridSize);
|
||||
}
|
||||
|
||||
private T _getDirect(int x, int y) {
|
||||
if (x<0 || x>=gridSize || y<0 || y>=gridSize) return null;
|
||||
return super.get(x + y * gridSize);
|
||||
}
|
||||
private boolean _setDirect(int x, int y, T t) {
|
||||
if (x<0 || x>=gridSize || y<0 || y>=gridSize) return false;
|
||||
super.set(x + y * gridSize, t);
|
||||
return true;
|
||||
}
|
||||
private T _swapDirect(int x, int y, T t) {
|
||||
if (x<0 || x>=gridSize || y<0 || y>=gridSize) return null;
|
||||
return super.set(x + y * gridSize, t);
|
||||
}
|
||||
|
||||
// Return false if haven't changed. Return true if it did
|
||||
public boolean move(int newCenterX, int newCenterY) {
|
||||
if (centerX == newCenterX && centerY == newCenterY) return false;
|
||||
int deltaX = newCenterX - centerX;
|
||||
int deltaY = newCenterY - centerY;
|
||||
|
||||
// if the x or z offset is equal to or greater than
|
||||
// the total width, just delete the current data
|
||||
// and update the centerX and/or centerZ
|
||||
if (Math.abs(deltaX) >= gridSize || Math.abs(deltaY) >= gridSize)
|
||||
{
|
||||
clear();
|
||||
// update the new center
|
||||
centerX = newCenterX;
|
||||
centerY = newCenterY;
|
||||
return true;
|
||||
}
|
||||
centerX = newCenterX;
|
||||
centerY = newCenterY;
|
||||
|
||||
// X
|
||||
if (deltaX >= 0 && deltaY >= 0)
|
||||
{
|
||||
// move everything over to the left-up (as the center moves to the right-down)
|
||||
for (int x = 0; x < gridSize; x++)
|
||||
{
|
||||
for (int y = 0; y < gridSize; y++)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (deltaX < 0 && deltaY >= 0)
|
||||
{
|
||||
// move everything over to the right-up (as the center moves to the left-down)
|
||||
for (int x = gridSize - 1; x >= 0; x--)
|
||||
{
|
||||
for (int y = 0; y < gridSize; y++)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (deltaX >= 0 && deltaY < 0)
|
||||
{
|
||||
// move everything over to the left-down (as the center moves to the right-up)
|
||||
for (int x = 0; x < gridSize; x++)
|
||||
{
|
||||
for (int y = gridSize - 1; y >= 0; y--)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
else //if (deltaX < 0 && deltaY < 0)
|
||||
{
|
||||
// move everything over to the right-down (as the center moves to the left-up)
|
||||
for (int x = gridSize - 1; x >= 0; x--)
|
||||
{
|
||||
for (int y = gridSize - 1; y >= 0; y--)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean move(int newCenterX, int newCenterY, Consumer<? super T> d) {
|
||||
if (centerX == newCenterX && centerY == newCenterY) return false;
|
||||
int deltaX = newCenterX - centerX;
|
||||
int deltaY = newCenterY - centerY;
|
||||
|
||||
// if the x or z offset is equal to or greater than
|
||||
// the total width, just delete the current data
|
||||
// and update the centerX and/or centerZ
|
||||
if (Math.abs(deltaX) >= gridSize || Math.abs(deltaY) >= gridSize)
|
||||
{
|
||||
clear(d);
|
||||
// update the new center
|
||||
centerX = newCenterX;
|
||||
centerY = newCenterY;
|
||||
return true;
|
||||
}
|
||||
centerX = newCenterX;
|
||||
centerY = newCenterY;
|
||||
|
||||
// Dealloc stuff
|
||||
for (int x=0; x<gridSize; x++) {
|
||||
for (int y=0; y<gridSize; y++) {
|
||||
if (x-deltaX<0 || y-deltaY<0 ||
|
||||
x-deltaX>=gridSize || y-deltaY>=gridSize) {
|
||||
T t = _getDirect(x,y);
|
||||
if (t!=null) d.accept(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// X
|
||||
if (deltaX >= 0 && deltaY >= 0)
|
||||
{
|
||||
// move everything over to the left-up (as the center moves to the right-down)
|
||||
for (int x = 0; x < gridSize; x++)
|
||||
{
|
||||
for (int y = 0; y < gridSize; y++)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (deltaX < 0 && deltaY >= 0)
|
||||
{
|
||||
// move everything over to the right-up (as the center moves to the left-down)
|
||||
for (int x = gridSize - 1; x >= 0; x--)
|
||||
{
|
||||
for (int y = 0; y < gridSize; y++)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (deltaX >= 0 && deltaY < 0)
|
||||
{
|
||||
// move everything over to the left-down (as the center moves to the right-up)
|
||||
for (int x = 0; x < gridSize; x++)
|
||||
{
|
||||
for (int y = gridSize - 1; y >= 0; y--)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
else //if (deltaX < 0 && deltaY < 0)
|
||||
{
|
||||
// move everything over to the right-down (as the center moves to the left-up)
|
||||
for (int x = gridSize - 1; x >= 0; x--)
|
||||
{
|
||||
for (int y = gridSize - 1; y >= 0; y--)
|
||||
{
|
||||
_setDirect(x, y, _getDirect(x+deltaX, y+deltaY));
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// TODO: This is unused but may be useful later on.
|
||||
/*
|
||||
public final MovableGridList<T> subGrid(int gridCentreToEdge, int newCenterX, int newCenterY) {
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MovableGridList[" + centerX + "," + centerY + "] " + gridSize + "*" + gridSize + "[" + size() + "]";
|
||||
}
|
||||
|
||||
public String toDetailString() {
|
||||
StringBuilder str = new StringBuilder("\n");
|
||||
int i = 0;
|
||||
str.append(this);
|
||||
str.append("\n");
|
||||
for (T t : this) {
|
||||
|
||||
str.append(t!=null ? t.toString() : "NULL");
|
||||
str.append(", ");
|
||||
i++;
|
||||
if (i % gridSize == 0) {
|
||||
str.append("\n");
|
||||
}
|
||||
}
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package com.seibel.lod.core.util.gridList;
|
||||
|
||||
import com.seibel.lod.core.objects.DHRegionPos;
|
||||
import com.seibel.lod.core.objects.Pos2D;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
|
||||
|
||||
@@ -32,9 +32,11 @@ import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
|
||||
public interface IVersionConstants extends IBindable
|
||||
{
|
||||
/** @return the minimum height blocks can be generated */
|
||||
@Deprecated // This changes per world!
|
||||
int getMinimumWorldHeight();
|
||||
|
||||
/** @return the number of generations call per thread. */
|
||||
@Deprecated // No longer used
|
||||
default int getWorldGenerationCountPerThread() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
-59
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.wrapperInterfaces.block;
|
||||
|
||||
import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.enums.config.EBlocksToAvoid;
|
||||
import com.seibel.lod.core.objects.DHBlockPos;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
|
||||
|
||||
public abstract class IBlockDetailWrapper
|
||||
{
|
||||
// Note: ALL value should be lazily-calculated
|
||||
|
||||
// Note: This should be lazily-calculated if block needs tinting to be resolved
|
||||
public abstract int getAndResolveFaceColor(ELodDirection dir, IChunkWrapper chunk, DHBlockPos blockPos);
|
||||
public abstract boolean hasFaceCullingFor(ELodDirection dir);
|
||||
public abstract boolean hasNoCollision();
|
||||
public abstract boolean noFaceIsFullFace();
|
||||
|
||||
public abstract String serialize();
|
||||
|
||||
protected abstract boolean isSame(IBlockDetailWrapper iBlockDetail);
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof IBlockDetailWrapper)) return false;
|
||||
return isSame((IBlockDetailWrapper)o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return serialize();
|
||||
}
|
||||
|
||||
public boolean shouldRender(EBlocksToAvoid mode)
|
||||
{
|
||||
return !((mode.noCollision && hasNoCollision()) || (mode.nonFull && noFaceIsFullFace()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+10
@@ -1,5 +1,15 @@
|
||||
package com.seibel.lod.core.wrapperInterfaces.block;
|
||||
|
||||
import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.enums.config.EBlocksToAvoid;
|
||||
import com.seibel.lod.core.objects.DHBlockPos;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
|
||||
public interface IBlockStateWrapper {
|
||||
String serialize();
|
||||
|
||||
// TODO:
|
||||
// boolean hasFaceCullingFor(ELodDirection dir);
|
||||
// boolean hasNoCollision();
|
||||
// boolean noFaceIsFullFace();
|
||||
}
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
|
||||
package com.seibel.lod.core.wrapperInterfaces.chunk;
|
||||
|
||||
import com.seibel.lod.core.enums.ELodDirection;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
|
||||
import com.seibel.lod.core.objects.DHChunkPos;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
|
||||
@@ -38,8 +36,10 @@ public interface IChunkWrapper extends IBindable
|
||||
}
|
||||
int getMinBuildHeight();
|
||||
int getMaxBuildHeight();
|
||||
|
||||
|
||||
// FIXME: getHeightMapValue & getMaxY is the same! Which one to keep?
|
||||
int getHeightMapValue(int xRel, int zRel);
|
||||
int getMaxY(int x, int z);
|
||||
|
||||
@Deprecated
|
||||
int getChunkPosX();
|
||||
@@ -49,7 +49,6 @@ public interface IChunkWrapper extends IBindable
|
||||
int getRegionPosX();
|
||||
@Deprecated
|
||||
int getRegionPosZ();
|
||||
int getMaxY(int x, int z);
|
||||
int getMaxX();
|
||||
int getMaxZ();
|
||||
int getMinX();
|
||||
|
||||
-10
@@ -79,16 +79,6 @@ public interface ILodConfigWrapperSingleton extends IBindable
|
||||
EHorizontalQuality getHorizontalQuality();
|
||||
void setHorizontalQuality(EHorizontalQuality newHorizontalQuality);
|
||||
|
||||
EDropoffQuality getDropoffQuality();
|
||||
void setDropoffQuality(EDropoffQuality newDropoffQuality);
|
||||
default EDropoffQuality getResolvedDropoffQuality() {
|
||||
EDropoffQuality dropoffQuality = Config.Client.Graphics.Quality.dropoffQuality.get();
|
||||
if (dropoffQuality == EDropoffQuality.AUTO)
|
||||
dropoffQuality = Config.Client.Graphics.Quality.lodChunkRenderDistance.get() < 128 ?
|
||||
EDropoffQuality.SMOOTH_DROPOFF : EDropoffQuality.PERFORMANCE_FOCUSED;
|
||||
return dropoffQuality;
|
||||
}
|
||||
|
||||
public void setTransparency(ETransparency newTransparency);
|
||||
|
||||
public ETransparency getTransparency();
|
||||
|
||||
-9
@@ -179,15 +179,6 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
Config.Client.Graphics.Quality.horizontalQuality.set(newHorizontalQuality);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EDropoffQuality getDropoffQuality() {
|
||||
return Config.Client.Graphics.Quality.dropoffQuality.get();
|
||||
}
|
||||
@Override
|
||||
public void setDropoffQuality(EDropoffQuality newDropoffQuality) {
|
||||
Config.Client.Graphics.Quality.dropoffQuality.set(newDropoffQuality);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransparency(ETransparency newTransparency) {
|
||||
Config.Client.Graphics.Quality.transparency.set(newTransparency);
|
||||
|
||||
+1
-1
@@ -130,7 +130,7 @@ public interface IMinecraftClientWrapper extends IBindable
|
||||
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
|
||||
* Exit Code: -1 <br>
|
||||
*/
|
||||
void crashMinecraft(String errorMessage, Throwable exception);
|
||||
void crashMinecraft(String errorMessage, Throwable exception); //FIXME: Move to IMinecraftSharedWrapper
|
||||
|
||||
Object getOptionsObject();
|
||||
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod (formerly the LOD Mod),
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2022 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.wrapperInterfaces.world;
|
||||
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
|
||||
import com.seibel.lod.core.objects.DHBlockPos;
|
||||
|
||||
|
||||
/**
|
||||
* Contains everything related to biome colors.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 3-5-2022
|
||||
*/
|
||||
public interface IBiomeColorWrapperSingleton extends IBindable
|
||||
{
|
||||
IBiomeColorWrapperSingleton getInstance();
|
||||
|
||||
int getGrassColor(ILevelWrapper world, DHBlockPos blockPos);
|
||||
int getWaterColor(ILevelWrapper world, DHBlockPos blockPos);
|
||||
int getFoliageColor(ILevelWrapper world, DHBlockPos blockPos);
|
||||
}
|
||||
Reference in New Issue
Block a user