Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57c5b2d5fc | |||
| 50c5701836 | |||
| 18e075538d | |||
| b00e8a08e9 | |||
| ac4ab11a74 | |||
| c26631db57 | |||
| 1daa06fff4 | |||
| f3ef6f25f4 | |||
| ec012d9fd6 | |||
| fc90cf3377 | |||
| e1e42d1caf | |||
| 95ce29e355 | |||
| 0fd818b077 | |||
| ba59daf747 | |||
| b7d94c2ed1 | |||
| 7a057a8d53 | |||
| 49c6ab97a9 | |||
| ed0d80b37e | |||
| 9768728c92 | |||
| 0c68544f2f | |||
| b1f154a0ea | |||
| 628c9b071f | |||
| ed39b6181f | |||
| 1d6d712483 | |||
| 73c4f0ffcd | |||
| 48d1005be6 |
@@ -180,7 +180,7 @@ public class DhApi
|
|||||||
* This version should be updated whenever non-breaking fixes are added to the Distant Horizons API.
|
* This version should be updated whenever non-breaking fixes are added to the Distant Horizons API.
|
||||||
* @since API 1.0.0
|
* @since API 1.0.0
|
||||||
*/
|
*/
|
||||||
public static int getApiPatchVersion() { return ModInfo.API_PATH_VERSION; }
|
public static int getApiPatchVersion() { return ModInfo.API_PATCH_VERSION; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the mod's semantic version number in the format: Major.Minor.Patch
|
* Returns the mod's semantic version number in the format: Major.Minor.Patch
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public final class ModInfo
|
|||||||
public static final String NAME = "DistantHorizons";
|
public static final String NAME = "DistantHorizons";
|
||||||
/** Human-readable version of NAME */
|
/** Human-readable version of NAME */
|
||||||
public static final String READABLE_NAME = "Distant Horizons";
|
public static final String READABLE_NAME = "Distant Horizons";
|
||||||
public static final String VERSION = "2.2.0-a";
|
public static final String VERSION = "2.2.1-a";
|
||||||
/** Returns true if the current build is an unstable developer build, false otherwise. */
|
/** Returns true if the current build is an unstable developer build, false otherwise. */
|
||||||
public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
|
public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ public final class ModInfo
|
|||||||
/** This version should be updated whenever new methods are added to the DH API */
|
/** This version should be updated whenever new methods are added to the DH API */
|
||||||
public static final int API_MINOR_VERSION = 0;
|
public static final int API_MINOR_VERSION = 0;
|
||||||
/** This version should be updated whenever non-breaking fixes are added to the DH API */
|
/** This version should be updated whenever non-breaking fixes are added to the DH API */
|
||||||
public static final int API_PATH_VERSION = 0;
|
public static final int API_PATCH_VERSION = 1;
|
||||||
|
|
||||||
public static final String NETWORKING_RESOURCE_NAMESPACE = "distant_horizons";
|
public static final String NETWORKING_RESOURCE_NAMESPACE = "distant_horizons";
|
||||||
public static final String MULTIVERSE_PLUGIN_NAMESPACE = "world_control";
|
public static final String MULTIVERSE_PLUGIN_NAMESPACE = "world_control";
|
||||||
|
|||||||
@@ -552,8 +552,17 @@ public class ClientApi
|
|||||||
}
|
}
|
||||||
IDhClientLevel level = dhClientWorld.getOrLoadClientLevel(levelWrapper);
|
IDhClientLevel level = dhClientWorld.getOrLoadClientLevel(levelWrapper);
|
||||||
|
|
||||||
|
|
||||||
if (this.rendererDisabledBecauseOfExceptions)
|
if (this.rendererDisabledBecauseOfExceptions)
|
||||||
{
|
{
|
||||||
|
// re-enable rendering if the user toggles DH rendering
|
||||||
|
if (!Config.Client.quickEnableRendering.get())
|
||||||
|
{
|
||||||
|
LOGGER.info("DH Renderer re-enabled after exception. Some rendering issues may occur. Please reboot Minecraft if you see any rendering issues.");
|
||||||
|
this.rendererDisabledBecauseOfExceptions = false;
|
||||||
|
Config.Client.quickEnableRendering.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,9 +613,9 @@ public class ClientApi
|
|||||||
LOGGER.error("Unexpected Renderer error in render pass [" + renderPass + "]. Error: " + e.getMessage(), e);
|
LOGGER.error("Unexpected Renderer error in render pass [" + renderPass + "]. Error: " + e.getMessage(), e);
|
||||||
|
|
||||||
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!");
|
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!");
|
||||||
MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues.");
|
MC.sendChatMessage("\u00A74Renderer disabled to try preventing GL state corruption.");
|
||||||
MC.sendChatMessage("\u00A74Please restart your game to re-enable Distant Horizons' LOD rendering.");
|
MC.sendChatMessage("\u00A74Toggle DH rendering via the config UI to re-activate DH rendering.");
|
||||||
MC.sendChatMessage("\u00A74Exception detail: " + e);
|
MC.sendChatMessage("\u00A74Error: " + e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,13 +24,11 @@ import com.seibel.distanthorizons.core.config.Config;
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
|
import com.seibel.distanthorizons.core.generation.DhLightingEngine;
|
||||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.level.IDhServerLevel;
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
|
||||||
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||||
@@ -45,10 +43,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.RejectedExecutionException;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
/** Contains code and variables used by both {@link ClientApi} and {@link ServerApi} */
|
/** Contains code and variables used by both {@link ClientApi} and {@link ServerApi} */
|
||||||
public class SharedApi
|
public class SharedApi
|
||||||
@@ -65,6 +60,7 @@ public class SharedApi
|
|||||||
private static final Timer CHUNK_UPDATE_TIMER = TimerUtil.CreateTimer("ChunkUpdateTimer");
|
private static final Timer CHUNK_UPDATE_TIMER = TimerUtil.CreateTimer("ChunkUpdateTimer");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static AbstractDhWorld currentWorld;
|
private static AbstractDhWorld currentWorld;
|
||||||
private static int lastWorldGenTickDelta = 0;
|
private static int lastWorldGenTickDelta = 0;
|
||||||
private static long lastOverloadedLogMessageMsTime = 0;
|
private static long lastOverloadedLogMessageMsTime = 0;
|
||||||
@@ -258,7 +254,7 @@ public class SharedApi
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// neighboring chunk
|
// neighboring chunk
|
||||||
DhChunkPos neighbourPos = new DhChunkPos(chunkWrapper.getChunkPos().x + xOffset, chunkWrapper.getChunkPos().z + zOffset);
|
DhChunkPos neighbourPos = new DhChunkPos(chunkWrapper.getChunkPos().getX() + xOffset, chunkWrapper.getChunkPos().getZ() + zOffset);
|
||||||
IChunkWrapper neighbourChunk = dhLevel.getLevelWrapper().tryGetChunk(neighbourPos);
|
IChunkWrapper neighbourChunk = dhLevel.getLevelWrapper().tryGetChunk(neighbourPos);
|
||||||
if (neighbourChunk != null)
|
if (neighbourChunk != null)
|
||||||
{
|
{
|
||||||
@@ -275,36 +271,43 @@ public class SharedApi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static void bakeChunkLightingAndSendToLevelAsync(IChunkWrapper chunkWrapper, @Nullable ArrayList<IChunkWrapper> neighbourChunkList, IDhLevel dhLevel)
|
/** returning a {@link CompletableFuture} isn't necessary, but allows Intellij to properly show the full stack trace when debugging. */
|
||||||
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
|
private static CompletableFuture<Void> bakeChunkLightingAndSendToLevelAsync(IChunkWrapper chunkWrapper, @Nullable ArrayList<IChunkWrapper> neighbourChunkList, IDhLevel dhLevel)
|
||||||
{
|
{
|
||||||
// lighting the chunk needs to be done on a separate thread to prevent lagging any of the event threads
|
// lighting the chunk needs to be done on a separate thread to prevent lagging any of the event threads
|
||||||
ThreadPoolExecutor executor = ThreadPoolUtil.getLightPopulatorExecutor();
|
ThreadPoolExecutor executor = ThreadPoolUtil.getChunkToLodBuilderExecutor();
|
||||||
if (executor == null)
|
if (executor == null)
|
||||||
{
|
{
|
||||||
return;
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
executor.execute(() ->
|
return CompletableFuture.runAsync(() ->
|
||||||
{
|
{
|
||||||
//LOGGER.trace(chunkWrapper.getChunkPos() + " " + executor.getActiveCount() + " / " + executor.getQueue().size() + " - " + executor.getCompletedTaskCount());
|
//LOGGER.trace(chunkWrapper.getChunkPos() + " " + executor.getActiveCount() + " / " + executor.getQueue().size() + " - " + executor.getCompletedTaskCount());
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
boolean checkChunkHash = !Config.Client.Advanced.LodBuilding.disableUnchangedChunkCheck.get();
|
||||||
|
|
||||||
// check if this chunk has been converted into an LOD already
|
// check if this chunk has been converted into an LOD already
|
||||||
int oldChunkHash = dhLevel.getChunkHash(chunkWrapper.getChunkPos()); // shouldn't happen on the render thread since it may take a few moments to run
|
int oldChunkHash = dhLevel.getChunkHash(chunkWrapper.getChunkPos()); // shouldn't happen on the render thread since it may take a few moments to run
|
||||||
int newChunkHash = chunkWrapper.getBlockBiomeHashCode();
|
int newChunkHash = chunkWrapper.getBlockBiomeHashCode();
|
||||||
if (oldChunkHash == newChunkHash)
|
if (checkChunkHash)
|
||||||
{
|
{
|
||||||
// if the chunk hashes are the same then we don't need to bother with lighting the chunk
|
if (oldChunkHash == newChunkHash)
|
||||||
// or creating/updating the LODs
|
{
|
||||||
//LOGGER.info("skipping: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
|
// if the chunk hashes are the same then we don't need to bother with lighting the chunk
|
||||||
return;
|
// or creating/updating the LODs
|
||||||
}
|
//LOGGER.info("skipping: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
|
||||||
else
|
return;
|
||||||
{
|
}
|
||||||
//LOGGER.info("g: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
|
else
|
||||||
|
{
|
||||||
|
//LOGGER.info("g: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -357,13 +360,7 @@ public class SharedApi
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dhLevel.updateBeaconBeamsForChunk(chunkWrapper, nearbyChunkList);
|
||||||
|
|
||||||
// get this chunk's active beacons
|
|
||||||
List<BeaconBeamDTO> beaconBeamList = chunkWrapper.getAllActiveBeacons(nearbyChunkList);
|
|
||||||
dhLevel.setBeaconBeamsForChunk(chunkWrapper.getChunkPos(), beaconBeamList);
|
|
||||||
|
|
||||||
|
|
||||||
dhLevel.updateChunkAsync(chunkWrapper, newChunkHash);
|
dhLevel.updateChunkAsync(chunkWrapper, newChunkHash);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -389,9 +386,13 @@ public class SharedApi
|
|||||||
UPDATING_CHUNK_POS_SET.remove(chunkWrapper.getChunkPos());
|
UPDATING_CHUNK_POS_SET.remove(chunkWrapper.getChunkPos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}, executor);
|
||||||
|
}
|
||||||
|
catch (RejectedExecutionException ignore)
|
||||||
|
{
|
||||||
|
// the executor was shut down, it should be back up shortly and able to accept new jobs
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
catch (RejectedExecutionException ignore) { /* the executor was shut down, it should be back up shortly and able to accept new jobs */ }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,6 +106,8 @@ public class Config
|
|||||||
|
|
||||||
public static ConfigLinkedEntry quickEnableWorldGenerator = new ConfigLinkedEntry(Advanced.WorldGenerator.enableDistantGeneration);
|
public static ConfigLinkedEntry quickEnableWorldGenerator = new ConfigLinkedEntry(Advanced.WorldGenerator.enableDistantGeneration);
|
||||||
|
|
||||||
|
public static ConfigLinkedEntry quickLodCloudRendering = new ConfigLinkedEntry(Advanced.Graphics.GenericRendering.enableCloudRendering);
|
||||||
|
|
||||||
public static ConfigEntry<Boolean> optionsButton = new ConfigEntry.Builder<Boolean>()
|
public static ConfigEntry<Boolean> optionsButton = new ConfigEntry.Builder<Boolean>()
|
||||||
.set(true)
|
.set(true)
|
||||||
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
|
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
|
||||||
@@ -699,6 +701,17 @@ public class Config
|
|||||||
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
|
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static ConfigEntry<Boolean> disableBeaconDistanceCulling = new ConfigEntry.Builder<Boolean>()
|
||||||
|
.set(false)
|
||||||
|
.comment(""
|
||||||
|
+ "If true all beacons near the camera won't be drawn to prevent vanilla overdraw. \n"
|
||||||
|
+ "If false all beacons will be rendered. \n"
|
||||||
|
+ "\n"
|
||||||
|
+ "Generally this should be left as false. It's main purpose is for debugging\n"
|
||||||
|
+ "beacon updating/rendering.\n"
|
||||||
|
+ "")
|
||||||
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -780,6 +793,19 @@ public class Config
|
|||||||
+ "")
|
+ "")
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
public static ConfigEntry<Boolean> disableUnchangedChunkCheck = new ConfigEntry.Builder<Boolean>()
|
||||||
|
.set(false)
|
||||||
|
.comment(""
|
||||||
|
+ "Normally DH will attempt to skip creating LODs for chunks it's already seen\n"
|
||||||
|
+ "and that haven't changed.\n"
|
||||||
|
+ "\n"
|
||||||
|
+ "However sometimes that logic incorrecly prevents LODs from being updated.\n"
|
||||||
|
+ "Disabling this check may fix issues where LODs aren't updated after\n"
|
||||||
|
+ "blocks have been changed.\n"
|
||||||
|
+ "")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
/** Currently we always use the DH lighting engine because there's a high likelyhood of MC returning incorrect lighting otherwise */
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static ConfigEntry<Boolean> onlyUseDhLightingEngine = new ConfigEntry.Builder<Boolean>()
|
public static ConfigEntry<Boolean> onlyUseDhLightingEngine = new ConfigEntry.Builder<Boolean>()
|
||||||
.set(false)
|
.set(false)
|
||||||
|
|||||||
+1
-1
@@ -25,7 +25,7 @@ import com.seibel.distanthorizons.core.dataObjects.transformers.FullDataToRender
|
|||||||
import com.seibel.distanthorizons.core.file.DataSourcePool;
|
import com.seibel.distanthorizons.core.file.DataSourcePool;
|
||||||
import com.seibel.distanthorizons.core.file.IDataSource;
|
import com.seibel.distanthorizons.core.file.IDataSource;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView;
|
import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView;
|
||||||
|
|||||||
+1
-2
@@ -21,10 +21,9 @@ package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.api.DhApi;
|
import com.seibel.distanthorizons.api.DhApi;
|
||||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
|
|||||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
|
|||||||
+1
-1
@@ -28,7 +28,7 @@ import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArra
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||||
|
|||||||
+13
-12
@@ -31,7 +31,8 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
@@ -66,8 +67,8 @@ public class LodDataBuilder
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int sectionPosX = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().x);
|
int sectionPosX = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().getX());
|
||||||
int sectionPosZ = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().z);
|
int sectionPosZ = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().getZ());
|
||||||
long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
||||||
|
|
||||||
FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos);
|
FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos);
|
||||||
@@ -77,8 +78,8 @@ public class LodDataBuilder
|
|||||||
|
|
||||||
// compute the chunk dataSource offset
|
// compute the chunk dataSource offset
|
||||||
// this offset is used to determine where in the dataSource this chunk's data should go
|
// this offset is used to determine where in the dataSource this chunk's data should go
|
||||||
int chunkOffsetX = chunkWrapper.getChunkPos().x;
|
int chunkOffsetX = chunkWrapper.getChunkPos().getX();
|
||||||
if (chunkWrapper.getChunkPos().x < 0)
|
if (chunkWrapper.getChunkPos().getX() < 0)
|
||||||
{
|
{
|
||||||
// expected offset positions:
|
// expected offset positions:
|
||||||
// chunkPos -> offset
|
// chunkPos -> offset
|
||||||
@@ -105,8 +106,8 @@ public class LodDataBuilder
|
|||||||
}
|
}
|
||||||
chunkOffsetX *= LodUtil.CHUNK_WIDTH;
|
chunkOffsetX *= LodUtil.CHUNK_WIDTH;
|
||||||
|
|
||||||
int chunkOffsetZ = chunkWrapper.getChunkPos().z;
|
int chunkOffsetZ = chunkWrapper.getChunkPos().getZ();
|
||||||
if (chunkWrapper.getChunkPos().z < 0)
|
if (chunkWrapper.getChunkPos().getZ() < 0)
|
||||||
{
|
{
|
||||||
chunkOffsetZ = ((chunkOffsetZ) % FullDataSourceV2.NUMB_OF_CHUNKS_WIDE);
|
chunkOffsetZ = ((chunkOffsetZ) % FullDataSourceV2.NUMB_OF_CHUNKS_WIDE);
|
||||||
if (chunkOffsetZ != 0)
|
if (chunkOffsetZ != 0)
|
||||||
@@ -237,7 +238,7 @@ public class LodDataBuilder
|
|||||||
private static boolean blockVisible(IChunkWrapper chunkWrapper, int relBlockX, int blockY, int relBlockZ)
|
private static boolean blockVisible(IChunkWrapper chunkWrapper, int relBlockX, int blockY, int relBlockZ)
|
||||||
{
|
{
|
||||||
DhBlockPos originalBlockPos = new DhBlockPos(relBlockX,blockY,relBlockZ);
|
DhBlockPos originalBlockPos = new DhBlockPos(relBlockX,blockY,relBlockZ);
|
||||||
DhBlockPos testBlockPos = new DhBlockPos(relBlockX,blockY,relBlockZ);
|
final DhBlockPosMutable testBlockPos = new DhBlockPosMutable(relBlockX,blockY,relBlockZ);
|
||||||
|
|
||||||
// up/down
|
// up/down
|
||||||
if (blockInDirectionVisible(chunkWrapper, EDhDirection.UP, originalBlockPos, testBlockPos))
|
if (blockInDirectionVisible(chunkWrapper, EDhDirection.UP, originalBlockPos, testBlockPos))
|
||||||
@@ -272,20 +273,20 @@ public class LodDataBuilder
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
private static boolean blockInDirectionVisible(IChunkWrapper chunkWrapper, EDhDirection direction, DhBlockPos originalBlockPos, DhBlockPos testBlockPos)
|
private static boolean blockInDirectionVisible(IChunkWrapper chunkWrapper, EDhDirection direction, DhBlockPos originalBlockPos, DhBlockPosMutable testBlockPos)
|
||||||
{
|
{
|
||||||
originalBlockPos.mutateOffset(direction, testBlockPos);
|
originalBlockPos.mutateOffset(direction, testBlockPos);
|
||||||
|
|
||||||
// if the block is next to the border of a chunk, assume it's visible
|
// if the block is next to the border of a chunk, assume it's visible
|
||||||
if (testBlockPos.x < 0 || testBlockPos.x >= LodUtil.CHUNK_WIDTH)
|
if (testBlockPos.getX() < 0 || testBlockPos.getX() >= LodUtil.CHUNK_WIDTH)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (testBlockPos.z < 0 || testBlockPos.z >= LodUtil.CHUNK_WIDTH)
|
if (testBlockPos.getZ() < 0 || testBlockPos.getZ() >= LodUtil.CHUNK_WIDTH)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (testBlockPos.y < chunkWrapper.getMinBuildHeight() || testBlockPos.y > chunkWrapper.getMaxBuildHeight())
|
if (testBlockPos.getY() < chunkWrapper.getMinBuildHeight() || testBlockPos.getY() > chunkWrapper.getMaxBuildHeight())
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -202,7 +202,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable
|
|||||||
|
|
||||||
// log the start of this attempt
|
// log the start of this attempt
|
||||||
LOGGER.info("Attempting to determine sub-dimension for [" + MC_CLIENT.getWrappedClientLevel().getDimensionType().getDimensionName() + "]");
|
LOGGER.info("Attempting to determine sub-dimension for [" + MC_CLIENT.getWrappedClientLevel().getDimensionType().getDimensionName() + "]");
|
||||||
LOGGER.info("Player block pos in dimension: [" + this.playerData.playerBlockPos.x + "," + this.playerData.playerBlockPos.y + "," + this.playerData.playerBlockPos.z + "]");
|
LOGGER.info("Player block pos in dimension: [" + this.playerData.playerBlockPos.getX() + "," + this.playerData.playerBlockPos.getY() + "," + this.playerData.playerBlockPos.getZ() + "]");
|
||||||
LOGGER.info("Potential Sub Dimension folders: [" + this.potentialLevelFolders.size() + "]");
|
LOGGER.info("Potential Sub Dimension folders: [" + this.potentialLevelFolders.size() + "]");
|
||||||
|
|
||||||
SubDimCompare mostSimilarSubDim = null;
|
SubDimCompare mostSimilarSubDim = null;
|
||||||
@@ -315,7 +315,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable
|
|||||||
|
|
||||||
// get the player data for this dimension folder
|
// get the player data for this dimension folder
|
||||||
SubDimensionPlayerData testPlayerData = new SubDimensionPlayerData(testLevelFolder);
|
SubDimensionPlayerData testPlayerData = new SubDimensionPlayerData(testLevelFolder);
|
||||||
LOGGER.info("Last known player pos: [" + testPlayerData.playerBlockPos.x + "," + testPlayerData.playerBlockPos.y + "," + testPlayerData.playerBlockPos.z + "]");
|
LOGGER.info("Last known player pos: [" + testPlayerData.playerBlockPos.getX() + "," + testPlayerData.playerBlockPos.getY() + "," + testPlayerData.playerBlockPos.getZ() + "]");
|
||||||
|
|
||||||
// check if the block positions are close
|
// check if the block positions are close
|
||||||
int playerBlockDist = testPlayerData.playerBlockPos.getManhattanDistance(this.playerData.playerBlockPos);
|
int playerBlockDist = testPlayerData.playerBlockPos.getManhattanDistance(this.playerData.playerBlockPos);
|
||||||
|
|||||||
+5
-5
@@ -22,7 +22,7 @@ package com.seibel.distanthorizons.core.file.subDimMatching;
|
|||||||
|
|
||||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
|
||||||
@@ -127,9 +127,9 @@ public class SubDimensionPlayerData
|
|||||||
public void toTomlFile(CommentedFileConfig toml)
|
public void toTomlFile(CommentedFileConfig toml)
|
||||||
{
|
{
|
||||||
// player block pos
|
// player block pos
|
||||||
toml.add(PLAYER_BLOCK_POS_X_PATH, this.playerBlockPos.x);
|
toml.add(PLAYER_BLOCK_POS_X_PATH, this.playerBlockPos.getX());
|
||||||
toml.add(PLAYER_BLOCK_POS_Y_PATH, this.playerBlockPos.y);
|
toml.add(PLAYER_BLOCK_POS_Y_PATH, this.playerBlockPos.getY());
|
||||||
toml.add(PLAYER_BLOCK_POS_Z_PATH, this.playerBlockPos.z);
|
toml.add(PLAYER_BLOCK_POS_Z_PATH, this.playerBlockPos.getZ());
|
||||||
|
|
||||||
toml.save();
|
toml.save();
|
||||||
}
|
}
|
||||||
@@ -138,7 +138,7 @@ public class SubDimensionPlayerData
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "PlayerBlockPos: [" + this.playerBlockPos.x + "," + this.playerBlockPos.y + "," + this.playerBlockPos.z + "]";
|
return "PlayerBlockPos: [" + this.playerBlockPos.getX() + "," + this.playerBlockPos.getY() + "," + this.playerBlockPos.getZ() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -33,7 +33,7 @@ public class AdjacentChunkHolder
|
|||||||
{
|
{
|
||||||
for (int zOffset = -1; zOffset <= 1; zOffset++)
|
for (int zOffset = -1; zOffset <= 1; zOffset++)
|
||||||
{
|
{
|
||||||
DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.x + xOffset, centerChunkPos.z + zOffset);
|
DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.getX() + xOffset, centerChunkPos.getZ() + zOffset);
|
||||||
requestedAdjacentPositions.add(adjacentPos);
|
requestedAdjacentPositions.add(adjacentPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,13 +69,13 @@ public class AdjacentChunkHolder
|
|||||||
DhChunkPos centerPos = this.chunkArray[4].getChunkPos();
|
DhChunkPos centerPos = this.chunkArray[4].getChunkPos();
|
||||||
DhChunkPos offsetPos = centerWrapper.getChunkPos();
|
DhChunkPos offsetPos = centerWrapper.getChunkPos();
|
||||||
|
|
||||||
int offsetX = offsetPos.x - centerPos.x;
|
int offsetX = offsetPos.getX() - centerPos.getX();
|
||||||
if (offsetX < -1 || offsetX > 1)
|
if (offsetX < -1 || offsetX > 1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offsetZ = offsetPos.z - centerPos.z;
|
int offsetZ = offsetPos.getZ() - centerPos.getZ();
|
||||||
if (offsetZ < -1 || offsetZ > 1)
|
if (offsetZ < -1 || offsetZ > 1)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -91,18 +91,18 @@ public class AdjacentChunkHolder
|
|||||||
int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4);
|
int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4);
|
||||||
IChunkWrapper centerChunk = this.chunkArray[4];
|
IChunkWrapper centerChunk = this.chunkArray[4];
|
||||||
DhChunkPos centerPos = centerChunk.getChunkPos();
|
DhChunkPos centerPos = centerChunk.getChunkPos();
|
||||||
if (centerPos.x == chunkX && centerPos.z == chunkZ)
|
if (centerPos.getX() == chunkX && centerPos.getZ() == chunkZ)
|
||||||
{
|
{
|
||||||
return centerChunk;
|
return centerChunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offsetX = chunkX - centerPos.x;
|
int offsetX = chunkX - centerPos.getX();
|
||||||
if (offsetX < -1 || offsetX > 1)
|
if (offsetX < -1 || offsetX > 1)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offsetZ = chunkZ - centerPos.z;
|
int offsetZ = chunkZ - centerPos.getZ();
|
||||||
if (offsetZ < -1 || offsetZ > 1)
|
if (offsetZ < -1 || offsetZ > 1)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+155
-36
@@ -21,13 +21,17 @@ package com.seibel.distanthorizons.core.generation;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
@@ -49,15 +53,28 @@ public class DhLightingEngine
|
|||||||
* Since these objects are always mutated anyway, using a {@link ThreadLocal} will allow us to
|
* Since these objects are always mutated anyway, using a {@link ThreadLocal} will allow us to
|
||||||
* only create as many of these {@link DhBlockPos} as necessary.
|
* only create as many of these {@link DhBlockPos} as necessary.
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<DhBlockPos> PRIMARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPos());
|
private static final ThreadLocal<DhBlockPosMutable> PRIMARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPosMutable());
|
||||||
private static final ThreadLocal<DhBlockPos> SECONDARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPos());
|
private static final ThreadLocal<DhBlockPosMutable> SECONDARY_BLOCK_POS_REF = ThreadLocal.withInitial(() -> new DhBlockPosMutable());
|
||||||
|
|
||||||
|
/** if enabled will render each block light value when the lighting engine is run */
|
||||||
|
private static final boolean RENDER_BLOCK_LIGHT_WIREFRAME = false;
|
||||||
|
/** if enabled will render each sky light value when the lighting engine is run */
|
||||||
|
private static final boolean RENDER_SKY_LIGHT_WIREFRAME = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
private DhLightingEngine() { }
|
private DhLightingEngine() { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: depending on the implementation of {@link IChunkWrapper#setDhBlockLight(int, int, int, int)} and {@link IChunkWrapper#setDhSkyLight(int, int, int, int)}
|
* Note: depending on the implementation of {@link IChunkWrapper#setDhBlockLight(int, int, int, int)} and {@link IChunkWrapper#setDhSkyLight(int, int, int, int)}
|
||||||
* the light values may be stored in the wrapper itself instead of the wrapped chunk object.
|
* the light values may be stored in the wrapper itself instead of the wrapped chunk object.
|
||||||
@@ -76,12 +93,12 @@ public class DhLightingEngine
|
|||||||
|
|
||||||
|
|
||||||
// try-finally to handle the stableArray resources
|
// try-finally to handle the stableArray resources
|
||||||
StableLightPosStack blockLightPosQueue = null;
|
StableLightPosStack blockLightWorldPosQueue = null;
|
||||||
StableLightPosStack skyLightPosQueue = null;
|
StableLightPosStack skyLightWorldPosQueue = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
blockLightPosQueue = StableLightPosStack.borrowStableLightPosArray();
|
blockLightWorldPosQueue = StableLightPosStack.borrowStableLightPosArray();
|
||||||
skyLightPosQueue = StableLightPosStack.borrowStableLightPosArray();
|
skyLightWorldPosQueue = StableLightPosStack.borrowStableLightPosArray();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -92,7 +109,7 @@ public class DhLightingEngine
|
|||||||
{
|
{
|
||||||
for (int zOffset = -1; zOffset <= 1; zOffset++)
|
for (int zOffset = -1; zOffset <= 1; zOffset++)
|
||||||
{
|
{
|
||||||
DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.x + xOffset, centerChunkPos.z + zOffset);
|
DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.getX() + xOffset, centerChunkPos.getZ() + zOffset);
|
||||||
requestedAdjacentPositions.add(adjacentPos);
|
requestedAdjacentPositions.add(adjacentPos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,11 +131,14 @@ public class DhLightingEngine
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// get and set the adjacent chunk's initial block lights
|
//==================//
|
||||||
final DhBlockPos relLightBlockPos = PRIMARY_BLOCK_POS_REF.get();
|
// set block lights //
|
||||||
final DhBlockPos relBlockPos = SECONDARY_BLOCK_POS_REF.get();
|
//==================//
|
||||||
|
|
||||||
ArrayList<DhBlockPos> blockLightPosList = chunk.getBlockLightPosList();
|
// get and set the adjacent chunk's initial block lights
|
||||||
|
final DhBlockPosMutable relLightBlockPos = PRIMARY_BLOCK_POS_REF.get();
|
||||||
|
|
||||||
|
ArrayList<DhBlockPos> blockLightPosList = chunk.getWorldBlockLightPosList();
|
||||||
for (int blockLightIndex = 0; blockLightIndex < blockLightPosList.size(); blockLightIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
|
for (int blockLightIndex = 0; blockLightIndex < blockLightPosList.size(); blockLightIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
|
||||||
{
|
{
|
||||||
DhBlockPos blockLightPos = blockLightPosList.get(blockLightIndex);
|
DhBlockPos blockLightPos = blockLightPosList.get(blockLightIndex);
|
||||||
@@ -127,14 +147,18 @@ public class DhLightingEngine
|
|||||||
// get the light
|
// get the light
|
||||||
IBlockStateWrapper blockState = chunk.getBlockState(relLightBlockPos);
|
IBlockStateWrapper blockState = chunk.getBlockState(relLightBlockPos);
|
||||||
int lightValue = blockState.getLightEmission();
|
int lightValue = blockState.getLightEmission();
|
||||||
blockLightPosQueue.push(blockLightPos.x, blockLightPos.y, blockLightPos.z, lightValue);
|
blockLightWorldPosQueue.push(blockLightPos.getX(), blockLightPos.getY(), blockLightPos.getZ(), lightValue);
|
||||||
|
|
||||||
// set the light
|
// set the light
|
||||||
blockLightPos.mutateToChunkRelativePos(relBlockPos);
|
chunk.setDhBlockLight(relLightBlockPos.getX(), relLightBlockPos.getY(), relLightBlockPos.getZ(), lightValue);
|
||||||
chunk.setDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, lightValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// set sky lights //
|
||||||
|
//================//
|
||||||
|
|
||||||
// get and set the adjacent chunk's initial skylights,
|
// get and set the adjacent chunk's initial skylights,
|
||||||
// if the dimension has skylights
|
// if the dimension has skylights
|
||||||
if (maxSkyLight > 0)
|
if (maxSkyLight > 0)
|
||||||
@@ -160,11 +184,11 @@ public class DhLightingEngine
|
|||||||
|
|
||||||
// add sky light to the queue
|
// add sky light to the queue
|
||||||
DhBlockPos skyLightPos = new DhBlockPos(chunk.getMinBlockX() + relX, y, chunk.getMinBlockZ() + relZ);
|
DhBlockPos skyLightPos = new DhBlockPos(chunk.getMinBlockX() + relX, y, chunk.getMinBlockZ() + relZ);
|
||||||
skyLightPosQueue.push(skyLightPos.x, skyLightPos.y, skyLightPos.z, maxSkyLight);
|
skyLightWorldPosQueue.push(skyLightPos.getX(), skyLightPos.getY(), skyLightPos.getZ(), maxSkyLight);
|
||||||
|
|
||||||
// set the chunk's sky light
|
// set the chunk's sky light
|
||||||
skyLightPos.mutateToChunkRelativePos(relBlockPos);
|
skyLightPos.mutateToChunkRelativePos(relLightBlockPos);
|
||||||
chunk.setDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, maxSkyLight);
|
chunk.setDhSkyLight(relLightBlockPos.getX(), relLightBlockPos.getY(), relLightBlockPos.getZ(), maxSkyLight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,14 +204,16 @@ public class DhLightingEngine
|
|||||||
}
|
}
|
||||||
|
|
||||||
// block light
|
// block light
|
||||||
this.propagateLightPosList(blockLightPosQueue, adjacentChunkHolder,
|
this.propagateLightPosList(blockLightWorldPosQueue, adjacentChunkHolder,
|
||||||
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z),
|
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
|
||||||
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhBlockLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, newLightValue));
|
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhBlockLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue),
|
||||||
|
true);
|
||||||
|
|
||||||
// sky light
|
// sky light
|
||||||
this.propagateLightPosList(skyLightPosQueue, adjacentChunkHolder,
|
this.propagateLightPosList(skyLightWorldPosQueue, adjacentChunkHolder,
|
||||||
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z),
|
(neighbourChunk, relBlockPos) -> neighbourChunk.getDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ()),
|
||||||
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.x, relBlockPos.y, relBlockPos.z, newLightValue));
|
(neighbourChunk, relBlockPos, newLightValue) -> neighbourChunk.setDhSkyLight(relBlockPos.getX(), relBlockPos.getY(), relBlockPos.getZ(), newLightValue),
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -195,8 +221,8 @@ public class DhLightingEngine
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
StableLightPosStack.returnStableLightPosArray(blockLightPosQueue);
|
StableLightPosStack.returnStableLightPosArray(blockLightWorldPosQueue);
|
||||||
StableLightPosStack.returnStableLightPosArray(skyLightPosQueue);
|
StableLightPosStack.returnStableLightPosArray(skyLightWorldPosQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -212,13 +238,14 @@ public class DhLightingEngine
|
|||||||
/** Applies each {@link LightPos} from the queue to the given set of {@link IChunkWrapper}'s. */
|
/** Applies each {@link LightPos} from the queue to the given set of {@link IChunkWrapper}'s. */
|
||||||
private void propagateLightPosList(
|
private void propagateLightPosList(
|
||||||
StableLightPosStack lightPosQueue, AdjacentChunkHolder adjacentChunkHolder,
|
StableLightPosStack lightPosQueue, AdjacentChunkHolder adjacentChunkHolder,
|
||||||
IGetLightFunc getLightFunc, ISetLightFunc setLightFunc)
|
IGetLightFunc getLightFunc, ISetLightFunc setLightFunc,
|
||||||
|
boolean propagatingBlockLights)
|
||||||
{
|
{
|
||||||
// these objects are saved so they can be mutated throughout the method,
|
// these objects are saved so they can be mutated throughout the method,
|
||||||
// this reduces the number of allocations necessary, reducing GC pressure
|
// this reduces the number of allocations necessary, reducing GC pressure
|
||||||
final LightPos lightPos = new LightPos(0, 0, 0, 0);
|
final LightPos lightPos = new LightPos(0, 0, 0, 0);
|
||||||
final DhBlockPos neighbourBlockPos = PRIMARY_BLOCK_POS_REF.get();
|
final DhBlockPosMutable neighbourBlockPos = PRIMARY_BLOCK_POS_REF.get();
|
||||||
final DhBlockPos relNeighbourBlockPos = SECONDARY_BLOCK_POS_REF.get();
|
final DhBlockPosMutable relNeighbourBlockPos = SECONDARY_BLOCK_POS_REF.get();
|
||||||
|
|
||||||
|
|
||||||
// update each light position
|
// update each light position
|
||||||
@@ -239,14 +266,14 @@ public class DhLightingEngine
|
|||||||
|
|
||||||
|
|
||||||
// only continue if the light position is inside one of our chunks
|
// only continue if the light position is inside one of our chunks
|
||||||
IChunkWrapper neighbourChunk = adjacentChunkHolder.getByBlockPos(neighbourBlockPos.x, neighbourBlockPos.z);
|
IChunkWrapper neighbourChunk = adjacentChunkHolder.getByBlockPos(neighbourBlockPos.getX(), neighbourBlockPos.getZ());
|
||||||
if (neighbourChunk == null)
|
if (neighbourChunk == null)
|
||||||
{
|
{
|
||||||
// the light pos is outside our generator's range, ignore it
|
// the light pos is outside our generator's range, ignore it
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (relNeighbourBlockPos.y < neighbourChunk.getMinNonEmptyHeight() || relNeighbourBlockPos.y > neighbourChunk.getMaxBuildHeight())
|
if (relNeighbourBlockPos.getY() < neighbourChunk.getMinNonEmptyHeight() || relNeighbourBlockPos.getY() > neighbourChunk.getMaxBuildHeight())
|
||||||
{
|
{
|
||||||
// the light pos is outside the chunk's min/max height,
|
// the light pos is outside the chunk's min/max height,
|
||||||
// this can happen if given a chunk that hasn't finished generating
|
// this can happen if given a chunk that hasn't finished generating
|
||||||
@@ -273,16 +300,103 @@ public class DhLightingEngine
|
|||||||
|
|
||||||
// now that light has been propagated to this blockPos
|
// now that light has been propagated to this blockPos
|
||||||
// we need to queue it up so its neighbours can be propagated as well
|
// we need to queue it up so its neighbours can be propagated as well
|
||||||
lightPosQueue.push(neighbourBlockPos.x, neighbourBlockPos.y, neighbourBlockPos.z, targetLevel);
|
lightPosQueue.push(neighbourBlockPos.getX(), neighbourBlockPos.getY(), neighbourBlockPos.getZ(), targetLevel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// can be enable if troubleshooting lighting issues
|
||||||
|
if (RENDER_BLOCK_LIGHT_WIREFRAME && propagatingBlockLights)
|
||||||
|
{
|
||||||
|
RenderDhLightValuesAsWireframe(adjacentChunkHolder, true);
|
||||||
|
}
|
||||||
|
else if (RENDER_SKY_LIGHT_WIREFRAME && !propagatingBlockLights)
|
||||||
|
{
|
||||||
|
RenderDhLightValuesAsWireframe(adjacentChunkHolder, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// propagation complete
|
// propagation complete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// debugging //
|
||||||
|
//===========//
|
||||||
|
|
||||||
|
/** Draw a wireframe representing each block's light value */
|
||||||
|
private static void RenderDhLightValuesAsWireframe(AdjacentChunkHolder adjacentChunkHolder, boolean renderBlockLights)
|
||||||
|
{
|
||||||
|
for (IChunkWrapper chunk : adjacentChunkHolder.chunkArray)
|
||||||
|
{
|
||||||
|
if (chunk == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int chunkMinX = chunk.getMinBlockX();
|
||||||
|
int chunkMinZ = chunk.getMinBlockZ();
|
||||||
|
|
||||||
|
int minY = chunk.getMinNonEmptyHeight();
|
||||||
|
int maxY = chunk.getMaxNonEmptyHeight();
|
||||||
|
|
||||||
|
// check each position's light
|
||||||
|
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||||
|
{
|
||||||
|
for (int y = minY; y < maxY; y++)
|
||||||
|
{
|
||||||
|
int lightValue = renderBlockLights? chunk.getDhBlockLight(x, y, z) : chunk.getDhSkyLight(x, y, z);
|
||||||
|
if (lightValue != LodUtil.MIN_MC_LIGHT)
|
||||||
|
{
|
||||||
|
// hotter colors for more intense light
|
||||||
|
Color color;
|
||||||
|
if (lightValue >= 14)
|
||||||
|
{
|
||||||
|
color = Color.WHITE;
|
||||||
|
}
|
||||||
|
else if (lightValue >= 10)
|
||||||
|
{
|
||||||
|
color = Color.PINK;
|
||||||
|
}
|
||||||
|
else if (lightValue >= 6)
|
||||||
|
{
|
||||||
|
color = Color.YELLOW;
|
||||||
|
}
|
||||||
|
else if (lightValue >= 4)
|
||||||
|
{
|
||||||
|
color = Color.ORANGE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = Color.RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// a color can be set to null if you only want to troubleshoot up to a certain light level
|
||||||
|
if (color != null)
|
||||||
|
{
|
||||||
|
DebugRenderer.makeParticle(
|
||||||
|
new DebugRenderer.BoxParticle(
|
||||||
|
new DebugRenderer.Box(DhSectionPos.encode((byte) 0, chunkMinX + x, chunkMinZ + z), y, y + 1, 0.2f, color),
|
||||||
|
10.0, 0f
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
// helper classes //
|
// helper classes //
|
||||||
//================//
|
//================//
|
||||||
@@ -293,7 +407,7 @@ public class DhLightingEngine
|
|||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
interface ISetLightFunc { void setLight(IChunkWrapper chunk, DhBlockPos pos, int lightValue); }
|
interface ISetLightFunc { void setLight(IChunkWrapper chunk, DhBlockPos pos, int lightValue); }
|
||||||
|
|
||||||
private static class LightPos extends DhBlockPos
|
private static class LightPos extends DhBlockPosMutable
|
||||||
{
|
{
|
||||||
public int lightValue;
|
public int lightValue;
|
||||||
|
|
||||||
@@ -303,6 +417,11 @@ public class DhLightingEngine
|
|||||||
this.lightValue = lightValue;
|
this.lightValue = lightValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() { return this.lightValue+" - ["+ this.x +", "+ this.y +", "+ this.z +"]"; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,9 +521,9 @@ public class DhLightingEngine
|
|||||||
{
|
{
|
||||||
int subIndex = this.index * INTS_PER_LIGHT_POS;
|
int subIndex = this.index * INTS_PER_LIGHT_POS;
|
||||||
|
|
||||||
pos.x = this.lightPositions.getInt(subIndex);
|
pos.setX(this.lightPositions.getInt(subIndex));
|
||||||
pos.y = this.lightPositions.getInt(subIndex + 1);
|
pos.setY(this.lightPositions.getInt(subIndex + 1));
|
||||||
pos.z = this.lightPositions.getInt(subIndex + 2);
|
pos.setZ(this.lightPositions.getInt(subIndex + 2));
|
||||||
pos.lightValue = this.lightPositions.getInt(subIndex + 3);
|
pos.lightValue = this.lightPositions.getInt(subIndex + 3);
|
||||||
|
|
||||||
this.index--;
|
this.index--;
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.generation;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker;
|
import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker;
|
||||||
import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult;
|
import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.render.LodQuadTree;
|
import com.seibel.distanthorizons.core.render.LodQuadTree;
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -27,7 +27,7 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.generation.tasks.*;
|
import com.seibel.distanthorizons.core.generation.tasks.*;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
@@ -456,8 +456,8 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
|||||||
case VANILLA_CHUNKS:
|
case VANILLA_CHUNKS:
|
||||||
{
|
{
|
||||||
return this.generator.generateChunks(
|
return this.generator.generateChunks(
|
||||||
chunkPosMin.x,
|
chunkPosMin.getX(),
|
||||||
chunkPosMin.z,
|
chunkPosMin.getZ(),
|
||||||
granularity,
|
granularity,
|
||||||
targetDataDetail,
|
targetDataDetail,
|
||||||
generatorMode,
|
generatorMode,
|
||||||
@@ -482,8 +482,8 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
|||||||
case API_CHUNKS:
|
case API_CHUNKS:
|
||||||
{
|
{
|
||||||
return this.generator.generateApiChunks(
|
return this.generator.generateApiChunks(
|
||||||
chunkPosMin.x,
|
chunkPosMin.getX(),
|
||||||
chunkPosMin.z,
|
chunkPosMin.getZ(),
|
||||||
granularity,
|
granularity,
|
||||||
targetDataDetail,
|
targetDataDetail,
|
||||||
generatorMode,
|
generatorMode,
|
||||||
|
|||||||
@@ -40,11 +40,9 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public abstract class AbstractDhLevel implements IDhLevel
|
public abstract class AbstractDhLevel implements IDhLevel
|
||||||
{
|
{
|
||||||
@@ -57,7 +55,7 @@ public abstract class AbstractDhLevel implements IDhLevel
|
|||||||
@Nullable
|
@Nullable
|
||||||
public BeaconBeamRepo beaconBeamRepo;
|
public BeaconBeamRepo beaconBeamRepo;
|
||||||
|
|
||||||
protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSave, 2_000);
|
protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSave, 500);
|
||||||
/** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */
|
/** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */
|
||||||
protected final ConcurrentHashMap<Long, HashSet<DhChunkPos>> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>();
|
protected final ConcurrentHashMap<Long, HashSet<DhChunkPos>> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>();
|
||||||
protected final ConcurrentHashMap<DhChunkPos, Integer> updatedChunkHashesByChunkPos = new ConcurrentHashMap<>();
|
protected final ConcurrentHashMap<DhChunkPos, Integer> updatedChunkHashesByChunkPos = new ConcurrentHashMap<>();
|
||||||
@@ -113,11 +111,15 @@ public abstract class AbstractDhLevel implements IDhLevel
|
|||||||
GenericObjectRenderer genericRenderer = this.getGenericRenderer();
|
GenericObjectRenderer genericRenderer = this.getGenericRenderer();
|
||||||
if (genericRenderer != null)
|
if (genericRenderer != null)
|
||||||
{
|
{
|
||||||
// only add clouds for certain dimension types
|
// only client levels can render clouds
|
||||||
if (!this.getLevelWrapper().hasCeiling()
|
if (this instanceof IDhClientLevel)
|
||||||
&& !this.getLevelWrapper().getDimensionType().isTheEnd())
|
|
||||||
{
|
{
|
||||||
this.cloudRenderHandler = new CloudRenderHandler(this, genericRenderer);
|
// only add clouds for certain dimension types
|
||||||
|
if (!this.getLevelWrapper().hasCeiling()
|
||||||
|
&& !this.getLevelWrapper().getDimensionType().isTheEnd())
|
||||||
|
{
|
||||||
|
this.cloudRenderHandler = new CloudRenderHandler((IDhClientLevel)this, genericRenderer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -182,7 +184,7 @@ public abstract class AbstractDhLevel implements IDhLevel
|
|||||||
|
|
||||||
ApiEventInjector.INSTANCE.fireAllEvents(
|
ApiEventInjector.INSTANCE.fireAllEvents(
|
||||||
DhApiChunkModifiedEvent.class,
|
DhApiChunkModifiedEvent.class,
|
||||||
new DhApiChunkModifiedEvent.EventParam(this.getLevelWrapper(), chunkPos.x, chunkPos.z));
|
new DhApiChunkModifiedEvent.EventParam(this.getLevelWrapper(), chunkPos.getX(), chunkPos.getZ()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -215,11 +217,12 @@ public abstract class AbstractDhLevel implements IDhLevel
|
|||||||
//=================//
|
//=================//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> newBeamList)
|
public void updateBeaconBeamsForChunk(IChunkWrapper chunkToUpdate, ArrayList<IChunkWrapper> nearbyChunkList)
|
||||||
{
|
{
|
||||||
if (this.beaconRenderHandler != null)
|
if (this.beaconRenderHandler != null)
|
||||||
{
|
{
|
||||||
this.beaconRenderHandler.setBeaconBeamsForChunk(chunkPos, newBeamList);
|
List<BeaconBeamDTO> activeBeamList = chunkToUpdate.getAllActiveBeacons(nearbyChunkList);
|
||||||
|
this.beaconRenderHandler.setBeaconBeamsForChunk(chunkToUpdate.getChunkPos(), activeBeamList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
|||||||
import com.seibel.distanthorizons.core.file.AbstractDataSourceHandler;
|
import com.seibel.distanthorizons.core.file.AbstractDataSourceHandler;
|
||||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.render.LodQuadTree;
|
import com.seibel.distanthorizons.core.render.LodQuadTree;
|
||||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV
|
|||||||
import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataSourceProvider;
|
import com.seibel.distanthorizons.core.file.fullDatafile.RemoteFullDataSourceProvider;
|
||||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
|||||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ package com.seibel.distanthorizons.core.level;
|
|||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
||||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.core.level;
|
package com.seibel.distanthorizons.core.level;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
|||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ public interface IDhLevel extends AutoCloseable
|
|||||||
void updateChunkAsync(IChunkWrapper chunk, int newChunkHash);
|
void updateChunkAsync(IChunkWrapper chunk, int newChunkHash);
|
||||||
|
|
||||||
void loadBeaconBeamsInPos(long pos);
|
void loadBeaconBeamsInPos(long pos);
|
||||||
void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> beamList);
|
void updateBeaconBeamsForChunk(IChunkWrapper chunkToUpdate, ArrayList<IChunkWrapper> nearbyChunkList);
|
||||||
void unloadBeaconBeamsInPos(long pos);
|
void unloadBeaconBeamsInPos(long pos);
|
||||||
|
|
||||||
FullDataSourceProviderV2 getFullDataProvider();
|
FullDataSourceProviderV2 getFullDataProvider();
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataSource
|
|||||||
import com.seibel.distanthorizons.core.generation.IFullDataSourceRetrievalQueue;
|
import com.seibel.distanthorizons.core.generation.IFullDataSourceRetrievalQueue;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public class F3Screen
|
|||||||
ThreadPoolExecutor worldGenPool = ThreadPoolUtil.getWorldGenExecutor();
|
ThreadPoolExecutor worldGenPool = ThreadPoolUtil.getWorldGenExecutor();
|
||||||
ThreadPoolExecutor fileHandlerPool = ThreadPoolUtil.getFileHandlerExecutor();
|
ThreadPoolExecutor fileHandlerPool = ThreadPoolUtil.getFileHandlerExecutor();
|
||||||
ThreadPoolExecutor updatePool = ThreadPoolUtil.getUpdatePropagatorExecutor();
|
ThreadPoolExecutor updatePool = ThreadPoolUtil.getUpdatePropagatorExecutor();
|
||||||
|
ThreadPoolExecutor lodBuilderPool = ThreadPoolUtil.getChunkToLodBuilderExecutor();
|
||||||
ThreadPoolExecutor bufferBuilderPool = ThreadPoolUtil.getBufferBuilderExecutor();
|
ThreadPoolExecutor bufferBuilderPool = ThreadPoolUtil.getBufferBuilderExecutor();
|
||||||
ThreadPoolExecutor bufferUploaderPool = ThreadPoolUtil.getBufferUploaderExecutor();
|
ThreadPoolExecutor bufferUploaderPool = ThreadPoolUtil.getBufferUploaderExecutor();
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ public class F3Screen
|
|||||||
messageList.add(getThreadPoolStatString("World Gen", worldGenPool));//"World Gen Tasks: 40/5304, (in progress: 7)");
|
messageList.add(getThreadPoolStatString("World Gen", worldGenPool));//"World Gen Tasks: 40/5304, (in progress: 7)");
|
||||||
messageList.add(getThreadPoolStatString("File Handler", fileHandlerPool));
|
messageList.add(getThreadPoolStatString("File Handler", fileHandlerPool));
|
||||||
messageList.add(getThreadPoolStatString("Update Propagator", updatePool));
|
messageList.add(getThreadPoolStatString("Update Propagator", updatePool));
|
||||||
|
messageList.add(getThreadPoolStatString("LOD Builder", lodBuilderPool));
|
||||||
messageList.add(getThreadPoolStatString("Buffer Builder", bufferBuilderPool));
|
messageList.add(getThreadPoolStatString("Buffer Builder", bufferBuilderPool));
|
||||||
messageList.add(getThreadPoolStatString("Buffer Uploader", bufferUploaderPool));
|
messageList.add(getThreadPoolStatString("Buffer Uploader", bufferUploaderPool));
|
||||||
messageList.add("");
|
messageList.add("");
|
||||||
|
|||||||
@@ -1,231 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Distant Horizons mod
|
|
||||||
* licensed under the GNU LGPL v3 License.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2020-2023 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.distanthorizons.core.pos;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class DhBlockPos
|
|
||||||
{
|
|
||||||
public static final boolean DO_CHECKS = false;
|
|
||||||
|
|
||||||
// 26 bits wide as that just encompasses the maximum possible value
|
|
||||||
// of +- 30,000,000 blocks in each direction. Yes this packing method
|
|
||||||
// is how Minecraft packs it.
|
|
||||||
|
|
||||||
// NOTE: Remember to ALWAYS check that DHBlockPos packing is EXACTLY
|
|
||||||
// the same as Minecraft's!!!!
|
|
||||||
public static final int PACKED_X_LENGTH = 26;
|
|
||||||
public static final int PACKED_Z_LENGTH = 26;
|
|
||||||
public static final int PACKED_Y_LENGTH = 12;
|
|
||||||
public static final long PACKED_X_MASK = (1L << PACKED_X_LENGTH) - 1L;
|
|
||||||
public static final long PACKED_Y_MASK = (1L << PACKED_Y_LENGTH) - 1L;
|
|
||||||
public static final long PACKED_Z_MASK = (1L << PACKED_Z_LENGTH) - 1L;
|
|
||||||
public static final int PACKED_Y_OFFSET = 0;
|
|
||||||
public static final int PACKED_Z_OFFSET = PACKED_Y_LENGTH;
|
|
||||||
public static final int PACKED_X_OFFSET = PACKED_Y_LENGTH + PACKED_Z_LENGTH;
|
|
||||||
|
|
||||||
/** Useful for methods that need a position passed in but won't actually be used */
|
|
||||||
public static final DhBlockPos ZERO = new DhBlockPos(0, 0, 0);
|
|
||||||
|
|
||||||
|
|
||||||
public int x;
|
|
||||||
public int y;
|
|
||||||
public int z;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public DhBlockPos(int x, int y, int z)
|
|
||||||
{
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.z = z;
|
|
||||||
}
|
|
||||||
public DhBlockPos()
|
|
||||||
{
|
|
||||||
this(0, 0, 0);
|
|
||||||
}
|
|
||||||
public DhBlockPos(DhBlockPos pos)
|
|
||||||
{
|
|
||||||
this(pos.x, pos.y, pos.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DhBlockPos(DhBlockPos2D pos, int y)
|
|
||||||
{
|
|
||||||
this(pos.x, y, pos.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long asLong(int x, int y, int z)
|
|
||||||
{
|
|
||||||
if (DO_CHECKS)
|
|
||||||
{
|
|
||||||
if ((x & ~PACKED_X_MASK) != 0)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("x is out of range: " + x);
|
|
||||||
}
|
|
||||||
if ((y & ~PACKED_Y_MASK) != 0)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("y is out of range: " + y);
|
|
||||||
}
|
|
||||||
if ((z & ~PACKED_Z_MASK) != 0)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("z is out of range: " + z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ((long) x & PACKED_X_MASK) << PACKED_X_OFFSET |
|
|
||||||
((long) y & PACKED_Y_MASK) << PACKED_Y_OFFSET |
|
|
||||||
((long) z & PACKED_Z_MASK) << PACKED_Z_OFFSET;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getX(long packed)
|
|
||||||
{ // X is at the top
|
|
||||||
return (int) (packed << (64 - PACKED_X_OFFSET - PACKED_X_LENGTH) >> (64 - PACKED_X_LENGTH));
|
|
||||||
}
|
|
||||||
public static int getY(long packed)
|
|
||||||
{ // Y is at the bottom
|
|
||||||
return (int) (packed << (64 - PACKED_Y_OFFSET - PACKED_Y_LENGTH) >> (64 - PACKED_Y_LENGTH));
|
|
||||||
}
|
|
||||||
public static int getZ(long packed)
|
|
||||||
{ // Z is at the middle
|
|
||||||
return (int) (packed << (64 - PACKED_Z_OFFSET - PACKED_Z_LENGTH) >> (64 - PACKED_Z_LENGTH));
|
|
||||||
}
|
|
||||||
public DhBlockPos(long packed)
|
|
||||||
{
|
|
||||||
this(getX(packed), getY(packed), getZ(packed));
|
|
||||||
}
|
|
||||||
|
|
||||||
public long asLong()
|
|
||||||
{
|
|
||||||
return asLong(x, y, z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** creates a new {@link DhBlockPos} with the given offset from the current pos. */
|
|
||||||
public DhBlockPos offset(EDhDirection direction) { return this.mutateOffset(direction, null); }
|
|
||||||
/** if not null, mutates "mutablePos" so it matches the current pos after being offset. Otherwise creates a new {@link DhBlockPos}. */
|
|
||||||
public DhBlockPos mutateOffset(EDhDirection direction, @Nullable DhBlockPos mutablePos) { return this.mutateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, mutablePos); }
|
|
||||||
|
|
||||||
public DhBlockPos offset(int x, int y, int z) { return this.mutateOffset(x,y,z, null); }
|
|
||||||
public DhBlockPos mutateOffset(int x, int y, int z, @Nullable DhBlockPos mutablePos)
|
|
||||||
{
|
|
||||||
int newX = this.x + x;
|
|
||||||
int newY = this.y + y;
|
|
||||||
int newZ = this.z + z;
|
|
||||||
|
|
||||||
if (mutablePos != null)
|
|
||||||
{
|
|
||||||
mutablePos.x = newX;
|
|
||||||
mutablePos.y = newY;
|
|
||||||
mutablePos.z = newZ;
|
|
||||||
|
|
||||||
return mutablePos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new DhBlockPos(newX, newY, newZ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a new {@link DhBlockPos} limits to a value between 0 and 15 (inclusive) */
|
|
||||||
public DhBlockPos convertToChunkRelativePos() { return this.mutateToChunkRelativePos(null); }
|
|
||||||
/**
|
|
||||||
* Limits the block position to a value between 0 and 15 (inclusive)
|
|
||||||
* If not null, mutates "mutableBlockPos"
|
|
||||||
*/
|
|
||||||
public DhBlockPos mutateToChunkRelativePos(@Nullable DhBlockPos mutableBlockPos)
|
|
||||||
{
|
|
||||||
// move the position into the range -15 and +15
|
|
||||||
int relX = (this.x % LodUtil.CHUNK_WIDTH);
|
|
||||||
// if the position is negative move it into the range 0 and 15
|
|
||||||
relX = (relX < 0) ? (relX + LodUtil.CHUNK_WIDTH) : relX;
|
|
||||||
|
|
||||||
int relZ = (this.z % LodUtil.CHUNK_WIDTH);
|
|
||||||
relZ = (relZ < 0) ? (relZ + LodUtil.CHUNK_WIDTH) : relZ;
|
|
||||||
|
|
||||||
// the y value shouldn't need to be changed
|
|
||||||
|
|
||||||
|
|
||||||
if (mutableBlockPos != null)
|
|
||||||
{
|
|
||||||
mutableBlockPos.x = relX;
|
|
||||||
mutableBlockPos.y = this.y;
|
|
||||||
mutableBlockPos.z = relZ;
|
|
||||||
|
|
||||||
return mutableBlockPos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return new DhBlockPos(relX, this.y, relZ);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Can be used to quickly determine the rough distance between two points<Br>
|
|
||||||
* or determine the taxi cab (manhattan) distance between two points. <Br><Br>
|
|
||||||
*
|
|
||||||
* Manhattan distance is equivalent to determining the distance between two street intersections,
|
|
||||||
* where you can only drive along each street, instead of directly to the other point.
|
|
||||||
*/
|
|
||||||
public int getManhattanDistance(DhBlockPos otherPos)
|
|
||||||
{
|
|
||||||
return Math.abs(this.x - otherPos.x) + Math.abs(this.y - otherPos.y) + Math.abs(this.z - otherPos.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o)
|
|
||||||
{
|
|
||||||
if (this == o) return true;
|
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
|
||||||
DhBlockPos that = (DhBlockPos) o;
|
|
||||||
return x == that.x && y == that.y && z == that.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode()
|
|
||||||
{
|
|
||||||
return Objects.hash(x, y, z);
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return "DHBlockPos[" +
|
|
||||||
"" + x +
|
|
||||||
", " + y +
|
|
||||||
", " + z +
|
|
||||||
']';
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void _DebugCheckPacker(int x, int y, int z, long expected)
|
|
||||||
{
|
|
||||||
long packed = asLong(x, y, z);
|
|
||||||
if (packed != expected)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Packed values don't match: " + packed + " != " + expected);
|
|
||||||
}
|
|
||||||
DhBlockPos pos = new DhBlockPos(packed);
|
|
||||||
if (pos.x != x || pos.y != y || pos.z != z)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Values after decode don't match: " + pos + " != " + x + ", " + y + ", " + z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -19,12 +19,23 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.core.pos;
|
package com.seibel.distanthorizons.core.pos;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* immutable <br><br>
|
||||||
|
*
|
||||||
|
* Dev note: if for some reason we want to store these as longs check the old commits. <br>
|
||||||
|
* That logic was removed since it wasn't needed at the time
|
||||||
|
*/
|
||||||
public class DhChunkPos
|
public class DhChunkPos
|
||||||
{
|
{
|
||||||
public final int x; // Low 32 bits
|
private final int x;
|
||||||
public final int z; // High 32 bits
|
public int getX() { return x; }
|
||||||
|
|
||||||
|
private final int z;
|
||||||
|
public int getZ() { return z; }
|
||||||
|
|
||||||
/** cached to improve hashing speed */
|
/** cached to improve hashing speed */
|
||||||
public final int hashCode;
|
public final int hashCode;
|
||||||
@@ -45,15 +56,14 @@ public class DhChunkPos
|
|||||||
}
|
}
|
||||||
public DhChunkPos(DhBlockPos blockPos)
|
public DhChunkPos(DhBlockPos blockPos)
|
||||||
{
|
{
|
||||||
// >> 4 is the Same as div 16
|
// >> 4 is the Same as divide by 16
|
||||||
this(blockPos.x >> 4, blockPos.z >> 4);
|
this(blockPos.getX() >> 4, blockPos.getZ() >> 4);
|
||||||
}
|
}
|
||||||
public DhChunkPos(DhBlockPos2D blockPos)
|
public DhChunkPos(DhBlockPos2D blockPos)
|
||||||
{
|
{
|
||||||
// >> 4 is the Same as div 16
|
// >> 4 is the Same as div 16
|
||||||
this(blockPos.x >> 4, blockPos.z >> 4);
|
this(blockPos.x >> 4, blockPos.z >> 4);
|
||||||
}
|
}
|
||||||
public DhChunkPos(long packed) { this(getXFromPackedLong(packed), getZFromPackedLong(packed)); }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -61,13 +71,8 @@ public class DhChunkPos
|
|||||||
// methods //
|
// methods //
|
||||||
//=========//
|
//=========//
|
||||||
|
|
||||||
public DhBlockPos center() { return new DhBlockPos(8 + this.x << 4, 0, 8 + this.z << 4); }
|
public DhBlockPos centerBlockPos() { return new DhBlockPos(8 + this.x << 4, 0, 8 + this.z << 4); }
|
||||||
public DhBlockPos corner() { return new DhBlockPos(this.x << 4, 0, this.z << 4); }
|
public DhBlockPos minCornerBlockPos() { return new DhBlockPos(this.x << 4, 0, this.z << 4); }
|
||||||
|
|
||||||
public static long toLong(int x, int z) { return ((long) x & 0xFFFFFFFFL) << 32 | (long) z & 0xFFFFFFFFL; }
|
|
||||||
|
|
||||||
private static int getXFromPackedLong(long chunkPos) { return (int) (chunkPos >> 32); }
|
|
||||||
private static int getZFromPackedLong(long chunkPos) { return (int) (chunkPos & 0xFFFFFFFFL); }
|
|
||||||
|
|
||||||
public int getMinBlockX() { return this.x << 4; }
|
public int getMinBlockX() { return this.x << 4; }
|
||||||
public int getMinBlockZ() { return this.z << 4; }
|
public int getMinBlockZ() { return this.z << 4; }
|
||||||
@@ -81,11 +86,10 @@ public class DhChunkPos
|
|||||||
int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH;
|
int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH;
|
||||||
int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH;
|
int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH;
|
||||||
|
|
||||||
return minBlockX <= pos.x && pos.x <= maxBlockX
|
return minBlockX <= pos.getX() && pos.getX() < maxBlockX
|
||||||
&& minBlockZ <= pos.z && pos.z <= maxBlockZ;
|
&& minBlockZ <= pos.getZ() && pos.getZ() < maxBlockZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLong() { return toLong(this.x, this.z); }
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
@@ -116,39 +120,4 @@ public class DhChunkPos
|
|||||||
@Override
|
@Override
|
||||||
public String toString() { return "C[" + this.x + "," + this.z + "]"; }
|
public String toString() { return "C[" + this.x + "," + this.z + "]"; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=======================//
|
|
||||||
// static helper methods //
|
|
||||||
//=======================//
|
|
||||||
|
|
||||||
public static void _DebugCheckPacker(int x, int z, long expected)
|
|
||||||
{
|
|
||||||
long packed = toLong(x, z);
|
|
||||||
if (packed != expected)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Packed values don't match: " + packed + " != " + expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
DhChunkPos pos = new DhChunkPos(packed);
|
|
||||||
if (pos.x != x || pos.z != z)
|
|
||||||
{
|
|
||||||
throw new IllegalArgumentException("Values after decode don't match: " + pos + " != " + x + ", " + z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return true if testPos is within the area defined by the min and max positions. */
|
|
||||||
public static boolean isChunkPosBetween(DhChunkPos minChunkPos, DhChunkPos testPos, DhChunkPos maxChunkPos)
|
|
||||||
{
|
|
||||||
int minChunkX = Math.min(minChunkPos.x, maxChunkPos.x);
|
|
||||||
int minChunkZ = Math.min(minChunkPos.z, maxChunkPos.z);
|
|
||||||
|
|
||||||
int maxChunkX = Math.max(minChunkPos.x, maxChunkPos.x);
|
|
||||||
int maxChunkZ = Math.max(minChunkPos.z, maxChunkPos.z);
|
|
||||||
|
|
||||||
return minChunkX <= testPos.x && testPos.x <= maxChunkX &&
|
|
||||||
minChunkZ <= testPos.z && testPos.z <= maxChunkZ;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.core.pos;
|
package com.seibel.distanthorizons.core.pos;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -47,6 +48,10 @@ public class DhLodPos implements Comparable<DhLodPos>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
|
||||||
public DhLodPos(byte detailLevel, int x, int z)
|
public DhLodPos(byte detailLevel, int x, int z)
|
||||||
{
|
{
|
||||||
this.detailLevel = detailLevel;
|
this.detailLevel = detailLevel;
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ public class DhLodUnit
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
|
||||||
public DhLodUnit(byte detailLevel, int numberOfLodSectionsWide)
|
public DhLodUnit(byte detailLevel, int numberOfLodSectionsWide)
|
||||||
{
|
{
|
||||||
this.detailLevel = detailLevel;
|
this.detailLevel = detailLevel;
|
||||||
@@ -43,6 +47,11 @@ public class DhLodUnit
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
|
||||||
/** @return the size of this LOD unit in Minecraft blocks */
|
/** @return the size of this LOD unit in Minecraft blocks */
|
||||||
public int toBlockWidth() { return BitShiftUtil.pow(this.numberOfLodSectionsWide, this.detailLevel); }
|
public int toBlockWidth() { return BitShiftUtil.pow(this.numberOfLodSectionsWide, this.detailLevel); }
|
||||||
/** @return the LOD Unit relative to the given block width and detail level */
|
/** @return the LOD Unit relative to the given block width and detail level */
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ package com.seibel.distanthorizons.core.pos;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||||
|
|
||||||
@@ -105,16 +107,16 @@ public class DhSectionPos
|
|||||||
/** Returns the section pos at the requested detail level containing the given BlockPos */
|
/** Returns the section pos at the requested detail level containing the given BlockPos */
|
||||||
public static long encodeContaining(byte outputSectionDetailLevel, DhBlockPos pos)
|
public static long encodeContaining(byte outputSectionDetailLevel, DhBlockPos pos)
|
||||||
{
|
{
|
||||||
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, false);
|
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.getX(), false);
|
||||||
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, false);
|
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.getZ(), false);
|
||||||
long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
||||||
return convertToDetailLevel(blockPos, outputSectionDetailLevel);
|
return convertToDetailLevel(blockPos, outputSectionDetailLevel);
|
||||||
}
|
}
|
||||||
/** Returns the section pos at the requested detail level containing the given ChunkPos */
|
/** Returns the section pos at the requested detail level containing the given ChunkPos */
|
||||||
public static long encodeContaining(byte outputSectionDetailLevel, DhChunkPos pos)
|
public static long encodeContaining(byte outputSectionDetailLevel, DhChunkPos pos)
|
||||||
{
|
{
|
||||||
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, true);
|
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.getX(), true);
|
||||||
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, true);
|
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.getZ(), true);
|
||||||
long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
||||||
return convertToDetailLevel(blockPos, outputSectionDetailLevel);
|
return convertToDetailLevel(blockPos, outputSectionDetailLevel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,23 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/** immutable */
|
||||||
public class Pos2D
|
public class Pos2D
|
||||||
{
|
{
|
||||||
public static final Pos2D ZERO = new Pos2D(0, 0);
|
public static final Pos2D ZERO = new Pos2D(0, 0);
|
||||||
|
|
||||||
public final int x;
|
private final int x;
|
||||||
public final int y;
|
public int getX() { return this.x; }
|
||||||
|
|
||||||
|
private final int y;
|
||||||
|
public int getY() { return this.y; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
|
||||||
public Pos2D(int x, int y)
|
public Pos2D(int x, int y)
|
||||||
{
|
{
|
||||||
this.x = x;
|
this.x = x;
|
||||||
@@ -40,6 +48,11 @@ public class Pos2D
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//======//
|
||||||
|
// math //
|
||||||
|
//======//
|
||||||
|
|
||||||
public Pos2D add(Pos2D other) { return new Pos2D(this.x + other.x, this.y + other.y); }
|
public Pos2D add(Pos2D other) { return new Pos2D(this.x + other.x, this.y + other.y); }
|
||||||
public Pos2D subtract(Pos2D other) { return new Pos2D(this.x - other.x, this.y - other.y); }
|
public Pos2D subtract(Pos2D other) { return new Pos2D(this.x - other.x, this.y - other.y); }
|
||||||
public Pos2D subtract(int value) { return new Pos2D(this.x - value, this.y - value); }
|
public Pos2D subtract(int value) { return new Pos2D(this.x - value, this.y - value); }
|
||||||
@@ -72,10 +85,17 @@ public class Pos2D
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Override
|
||||||
public int hashCode() { return Objects.hash(this.x, this.y); }
|
public int hashCode() { return Objects.hash(this.x, this.y); }
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() { return "[" + this.x + ", " + this.y + "]"; }
|
public String toString() { return "[" + this.x + ", " + this.y + "]"; }
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean equals(Object otherObj)
|
public boolean equals(Object otherObj)
|
||||||
{
|
{
|
||||||
if (otherObj == this)
|
if (otherObj == this)
|
||||||
|
|||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020-2023 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.distanthorizons.core.pos.blockPos;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* immutable <br><br>
|
||||||
|
*
|
||||||
|
* Dev note: if for some reason we want to store these as longs check the old commits. <br>
|
||||||
|
* That logic was removed since it wasn't needed at the time.
|
||||||
|
*
|
||||||
|
* @see DhBlockPosMutable
|
||||||
|
*/
|
||||||
|
public class DhBlockPos
|
||||||
|
{
|
||||||
|
/** Useful for methods that need a position passed in but won't actually be used */
|
||||||
|
public static final DhBlockPos ZERO = new DhBlockPos(0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
protected int x;
|
||||||
|
public int getX() { return this.x; }
|
||||||
|
|
||||||
|
protected int y;
|
||||||
|
public int getY() { return this.y; }
|
||||||
|
|
||||||
|
protected int z;
|
||||||
|
public int getZ() { return this.z; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
|
||||||
|
public DhBlockPos(int x, int y, int z)
|
||||||
|
{
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
public DhBlockPos() { this(0, 0, 0); }
|
||||||
|
public DhBlockPos(DhBlockPos pos) { this(pos.x, pos.y, pos.z); }
|
||||||
|
|
||||||
|
public DhBlockPos(DhBlockPos2D pos, int y) { this(pos.x, y, pos.z); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// offset //
|
||||||
|
//========//
|
||||||
|
|
||||||
|
/** creates a new {@link DhBlockPos} with the given offset from the current pos. */
|
||||||
|
public DhBlockPos createOffset(EDhDirection direction) { return this.mutateOrCreateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, null); }
|
||||||
|
/** if not null, mutates "mutablePos" so it matches the current pos after being offset. Otherwise creates a new {@link DhBlockPos}. */
|
||||||
|
public void mutateOffset(EDhDirection direction, @NotNull DhBlockPosMutable mutablePos) { this.mutateOrCreateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, mutablePos); }
|
||||||
|
|
||||||
|
public DhBlockPos createOffset(int x, int y, int z) { return this.mutateOrCreateOffset(x,y,z, null); }
|
||||||
|
public void mutateOffset(int x, int y, int z, @NotNull DhBlockPosMutable mutablePos) { this.mutateOrCreateOffset(x, y, z, mutablePos); }
|
||||||
|
|
||||||
|
protected DhBlockPos mutateOrCreateOffset(int x, int y, int z, @Nullable DhBlockPosMutable mutablePos)
|
||||||
|
{
|
||||||
|
int newX = this.x + x;
|
||||||
|
int newY = this.y + y;
|
||||||
|
int newZ = this.z + z;
|
||||||
|
|
||||||
|
if (mutablePos != null)
|
||||||
|
{
|
||||||
|
mutablePos.x = newX;
|
||||||
|
mutablePos.y = newY;
|
||||||
|
mutablePos.z = newZ;
|
||||||
|
|
||||||
|
return mutablePos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new DhBlockPos(newX, newY, newZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// chunk relative //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
/** Returns a new {@link DhBlockPos} limited to a value between 0 and 15 (inclusive) */
|
||||||
|
public DhBlockPos createChunkRelativePos() { return this.mutateOrCreateChunkRelativePos(null); }
|
||||||
|
/** Limits the input {@link DhBlockPos} to a value between 0 and 15 (inclusive) */
|
||||||
|
public void mutateToChunkRelativePos(DhBlockPosMutable mutableBlockPos) { this.mutateOrCreateChunkRelativePos(mutableBlockPos); }
|
||||||
|
/**
|
||||||
|
* Limits the block position to a value between 0 and 15 (inclusive)
|
||||||
|
* If not null, mutates "mutableBlockPos"
|
||||||
|
*
|
||||||
|
* @return the mutated or created {@link DhBlockPos}
|
||||||
|
*/
|
||||||
|
protected DhBlockPos mutateOrCreateChunkRelativePos(@Nullable DhBlockPosMutable mutableBlockPos)
|
||||||
|
{
|
||||||
|
int relX = convertWorldPosToChunkRelative(this.x);
|
||||||
|
// the y value shouldn't need to be changed
|
||||||
|
int relZ = convertWorldPosToChunkRelative(this.z);
|
||||||
|
|
||||||
|
|
||||||
|
if (mutableBlockPos != null)
|
||||||
|
{
|
||||||
|
mutableBlockPos.x = relX;
|
||||||
|
mutableBlockPos.y = this.y;
|
||||||
|
mutableBlockPos.z = relZ;
|
||||||
|
|
||||||
|
return mutableBlockPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new DhBlockPos(relX, this.y, relZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int convertWorldPosToChunkRelative(int xOrZ)
|
||||||
|
{
|
||||||
|
// move the position into the range -15 and +15
|
||||||
|
int relPos = (xOrZ % LodUtil.CHUNK_WIDTH);
|
||||||
|
// if the position is negative move it into the range 0 and 15
|
||||||
|
relPos = (relPos < 0) ? (relPos + LodUtil.CHUNK_WIDTH) : relPos;
|
||||||
|
return relPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// distance //
|
||||||
|
//==========//
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to quickly determine the rough distance between two points<Br>
|
||||||
|
* or determine the taxi cab (manhattan) distance between two points. <Br><Br>
|
||||||
|
*
|
||||||
|
* Manhattan distance is equivalent to determining the distance between two street intersections,
|
||||||
|
* where you can only drive along each street, instead of directly to the other point.
|
||||||
|
*/
|
||||||
|
public int getManhattanDistance(DhBlockPos otherPos)
|
||||||
|
{ return Math.abs(this.x - otherPos.x) + Math.abs(this.y - otherPos.y) + Math.abs(this.z - otherPos.z); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj)
|
||||||
|
{
|
||||||
|
if (this == obj)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (obj == null || this.getClass() != obj.getClass())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DhBlockPos that = (DhBlockPos) obj;
|
||||||
|
return this.x == that.x && this.y == that.y && this.z == that.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() { return Objects.hash(this.x, this.y, this.z); }
|
||||||
|
@Override
|
||||||
|
public String toString() { return "DHBlockPos["+ this.x +", "+ this.y +", "+ this.z +"]"; }
|
||||||
|
|
||||||
|
}
|
||||||
+6
-4
@@ -17,10 +17,12 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.seibel.distanthorizons.core.pos;
|
package com.seibel.distanthorizons.core.pos.blockPos;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.pos.Pos2D;
|
||||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||||
|
|
||||||
|
/** immutable */
|
||||||
public class DhBlockPos2D
|
public class DhBlockPos2D
|
||||||
{
|
{
|
||||||
public static final DhBlockPos2D ZERO = new DhBlockPos2D(0, 0);
|
public static final DhBlockPos2D ZERO = new DhBlockPos2D(0, 0);
|
||||||
@@ -41,11 +43,11 @@ public class DhBlockPos2D
|
|||||||
|
|
||||||
public DhBlockPos2D(DhBlockPos blockPos)
|
public DhBlockPos2D(DhBlockPos blockPos)
|
||||||
{
|
{
|
||||||
this.x = blockPos.x;
|
this.x = blockPos.getX();
|
||||||
this.z = blockPos.z;
|
this.z = blockPos.getZ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DhBlockPos2D fromPos2D(Pos2D pos) { return new DhBlockPos2D(pos.x, pos.y); }
|
public static DhBlockPos2D fromPos2D(Pos2D pos) { return new DhBlockPos2D(pos.getX(), pos.getY()); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020-2023 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.distanthorizons.core.pos.blockPos;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
|
|
||||||
|
public class DhBlockPosMutable extends DhBlockPos
|
||||||
|
{
|
||||||
|
/** Useful for methods that need a position passed in but won't actually be used */
|
||||||
|
public static final DhBlockPosMutable ZERO = new DhBlockPosMutable(0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
public void setX(int x) { this.x = x; }
|
||||||
|
public void setY(int y) { this.y = y; }
|
||||||
|
public void setZ(int z) { this.z = z; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
|
||||||
|
public DhBlockPosMutable(int x, int y, int z) { super(x,y,z); }
|
||||||
|
public DhBlockPosMutable() { super(0, 0, 0); }
|
||||||
|
public DhBlockPosMutable(DhBlockPos pos) { super(pos); }
|
||||||
|
|
||||||
|
public DhBlockPosMutable(DhBlockPos2D pos, int y) { super(pos.x, y, pos.z); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// offset //
|
||||||
|
//========//
|
||||||
|
|
||||||
|
/** @see DhBlockPos#createOffset(EDhDirection) */
|
||||||
|
public DhBlockPosMutable createOffset(EDhDirection direction) { return new DhBlockPosMutable(super.mutateOrCreateOffset(direction.getNormal().x, direction.getNormal().y, direction.getNormal().z, null)); }
|
||||||
|
/** @see DhBlockPos#createOffset(int, int, int) */
|
||||||
|
public DhBlockPosMutable createOffset(int x, int y, int z) { return new DhBlockPosMutable(this.mutateOrCreateOffset(x,y,z, null)); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// chunk relative //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
public DhBlockPosMutable createChunkRelativePos() { return new DhBlockPosMutable(this.mutateOrCreateChunkRelativePos(null)); }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,19 +19,16 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.core.render;
|
package com.seibel.distanthorizons.core.render;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.config.EDhApiHorizontalQuality;
|
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
|
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
||||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||||
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||||
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode;
|
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode;
|
||||||
@@ -253,11 +250,12 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
|||||||
ArrayList<LodRenderSection> nodesNeedingRetrieval,
|
ArrayList<LodRenderSection> nodesNeedingRetrieval,
|
||||||
ArrayList<LodRenderSection> nodesNeedingLoading)
|
ArrayList<LodRenderSection> nodesNeedingLoading)
|
||||||
{
|
{
|
||||||
//===============================//
|
//=====================//
|
||||||
// node and render section setup //
|
// get/create the node //
|
||||||
//===============================//
|
// and render section //
|
||||||
|
//=====================//
|
||||||
|
|
||||||
// make sure the node is created
|
// create the node
|
||||||
if (quadNode == null && this.isSectionPosInBounds(sectionPos)) // the position bounds should only fail when at the edge of the user's render distance
|
if (quadNode == null && this.isSectionPosInBounds(sectionPos)) // the position bounds should only fail when at the edge of the user's render distance
|
||||||
{
|
{
|
||||||
rootNode.setValue(sectionPos, new LodRenderSection(sectionPos, this, this.level, this.fullDataSourceProvider));
|
rootNode.setValue(sectionPos, new LodRenderSection(sectionPos, this, this.level, this.fullDataSourceProvider));
|
||||||
@@ -269,15 +267,12 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure the render section is created
|
// make sure the render section is created (shouldn't be necessary, but just in case)
|
||||||
LodRenderSection renderSection = quadNode.value;
|
LodRenderSection renderSection = quadNode.value;
|
||||||
// create a new render section if missing
|
|
||||||
if (renderSection == null)
|
if (renderSection == null)
|
||||||
{
|
{
|
||||||
LodRenderSection newRenderSection = new LodRenderSection(sectionPos, this, this.level, this.fullDataSourceProvider);
|
renderSection = new LodRenderSection(sectionPos, this, this.level, this.fullDataSourceProvider);
|
||||||
rootNode.setValue(sectionPos, newRenderSection);
|
rootNode.setValue(sectionPos, renderSection);
|
||||||
|
|
||||||
renderSection = newRenderSection; // TODO this never seemed to be called, is it necessary?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -286,20 +281,22 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
|||||||
// handle enabling, loading, //
|
// handle enabling, loading, //
|
||||||
// and disabling render sections //
|
// and disabling render sections //
|
||||||
//===============================//
|
//===============================//
|
||||||
|
|
||||||
//byte expectedDetailLevel = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + 3; // can be used instead of the following logic for testing
|
//byte expectedDetailLevel = DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL + 3; // can be used instead of the following logic for testing
|
||||||
byte expectedDetailLevel = this.calculateExpectedDetailLevel(playerPos, sectionPos);
|
byte expectedDetailLevel = this.calculateExpectedDetailLevel(playerPos, sectionPos);
|
||||||
expectedDetailLevel = (byte) Math.min(expectedDetailLevel, this.minRenderDetailLevel);
|
expectedDetailLevel = (byte) Math.min(expectedDetailLevel, this.minRenderDetailLevel);
|
||||||
expectedDetailLevel += DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
|
expectedDetailLevel += DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL;
|
||||||
|
|
||||||
|
|
||||||
if (DhSectionPos.getDetailLevel(sectionPos) > expectedDetailLevel)
|
if (DhSectionPos.getDetailLevel(sectionPos) > expectedDetailLevel)
|
||||||
{
|
{
|
||||||
// section detail level too high //
|
//=======================//
|
||||||
|
// detail level too high //
|
||||||
|
//=======================//
|
||||||
|
|
||||||
boolean thisPosIsRendering = renderSection.getRenderingEnabled();
|
boolean thisPosIsRendering = renderSection.getRenderingEnabled();
|
||||||
boolean allChildrenSectionsAreLoaded = true;
|
boolean allChildrenSectionsAreLoaded = true;
|
||||||
|
|
||||||
// recursively update all child render sections
|
// recursively update each child render section
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
QuadNode<LodRenderSection> childNode = quadNode.getChildByIndex(i);
|
QuadNode<LodRenderSection> childNode = quadNode.getChildByIndex(i);
|
||||||
@@ -307,6 +304,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
|||||||
allChildrenSectionsAreLoaded = childSectionLoaded && allChildrenSectionsAreLoaded;
|
allChildrenSectionsAreLoaded = childSectionLoaded && allChildrenSectionsAreLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!allChildrenSectionsAreLoaded)
|
if (!allChildrenSectionsAreLoaded)
|
||||||
{
|
{
|
||||||
// not all child positions are loaded yet, or this section is out of render range
|
// not all child positions are loaded yet, or this section is out of render range
|
||||||
@@ -314,94 +312,90 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// all child positions are loaded, disable this section and enable its children.
|
// onRenderingDisabled() needs to be fired before the children are enabled so beacons render correctly
|
||||||
renderSection.setRenderingEnabled(false);
|
if (renderSection.getRenderingEnabled())
|
||||||
|
{
|
||||||
|
renderSection.onRenderingDisabled();
|
||||||
|
|
||||||
|
// this position's rendering has been disabled due to children being rendered
|
||||||
|
DebugRenderer.makeParticle(new DebugRenderer.BoxParticle(new DebugRenderer.Box(renderSection.pos, 128f, 156f, 0.09f, Color.WHITE), 0.2, 32f));
|
||||||
|
}
|
||||||
|
|
||||||
// walk back down the tree and enable the child sections //TODO there are probably more efficient ways of doing this, but this will work for now
|
|
||||||
|
// walk back down the tree and enable each child section
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
QuadNode<LodRenderSection> childNode = quadNode.getChildByIndex(i);
|
QuadNode<LodRenderSection> childNode = quadNode.getChildByIndex(i);
|
||||||
boolean childSectionLoaded = this.recursivelyUpdateRenderSectionNode(playerPos, rootNode, childNode, DhSectionPos.getChildByIndex(sectionPos, i), parentSectionIsRendering, nodesNeedingRetrieval, nodesNeedingLoading);
|
this.recursivelyUpdateRenderSectionNode(playerPos, rootNode, childNode, DhSectionPos.getChildByIndex(sectionPos, i), parentSectionIsRendering, nodesNeedingRetrieval, nodesNeedingLoading);
|
||||||
allChildrenSectionsAreLoaded = childSectionLoaded && allChildrenSectionsAreLoaded;
|
|
||||||
}
|
|
||||||
if (!allChildrenSectionsAreLoaded)
|
|
||||||
{
|
|
||||||
// FIXME having world generation enabled in a pre-generated world that doesn't have any DH data can cause this to happen
|
|
||||||
// surprisingly reloadPos() doesn't appear to be the culprit, maybe there is an issue with reloading/changing the full data source?
|
|
||||||
//LOGGER.warn("Potential QuadTree concurrency issue. All child sections should be enabled and ready to render for pos: "+DhSectionPos.toString(sectionPos));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// disabling rendering must be done after the children are enabled
|
||||||
|
// otherwise holes may appear in the world, overlaps are less noticeable
|
||||||
|
renderSection.setRenderingEnabled(false);
|
||||||
|
|
||||||
// this section is now being rendered via its children
|
// this section is now being rendered via its children
|
||||||
return allChildrenSectionsAreLoaded;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO this should only equal the expected detail level, the (expectedDetailLevel-1) is a temporary fix to prevent corners from being cut out
|
// TODO this should only equal the expected detail level, the (expectedDetailLevel-1) is a temporary fix to prevent corners from being cut out
|
||||||
else if (DhSectionPos.getDetailLevel(sectionPos) == expectedDetailLevel || DhSectionPos.getDetailLevel(sectionPos) == expectedDetailLevel - 1)
|
else if (DhSectionPos.getDetailLevel(sectionPos) == expectedDetailLevel || DhSectionPos.getDetailLevel(sectionPos) == expectedDetailLevel - 1)
|
||||||
{
|
{
|
||||||
// this is the detail level we want to render //
|
//======================//
|
||||||
|
// desired detail level //
|
||||||
|
//======================//
|
||||||
|
|
||||||
|
|
||||||
/* Can be uncommented to easily debug a single render section. */
|
// prepare this section for rendering
|
||||||
/* Don't forget the disableRendering() at the bottom though. */
|
if (!renderSection.gpuUploadInProgress() && renderSection.renderBuffer == null)
|
||||||
//if (sectionPos.getDetailLevel() == 10
|
|
||||||
// &&
|
|
||||||
// (
|
|
||||||
// sectionPos.getX() == 0 &&
|
|
||||||
// sectionPos.getZ() == -4
|
|
||||||
// ))
|
|
||||||
{
|
{
|
||||||
// prepare this section for rendering
|
nodesNeedingLoading.add(renderSection);
|
||||||
// TODO this should fire for the lowest detail level first to improve loading speed
|
}
|
||||||
if (!renderSection.gpuUploadInProgress() && renderSection.renderBuffer == null)
|
|
||||||
|
// queue world gen if needed
|
||||||
|
if (!renderSection.isFullyGenerated())
|
||||||
|
{
|
||||||
|
nodesNeedingRetrieval.add(renderSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update debug if needed
|
||||||
|
if (Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus.get())
|
||||||
|
{
|
||||||
|
this.debugRenderSections.add(renderSection);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// wait for the parent to disable before enabling this section, so we don't have a hole
|
||||||
|
if (!parentSectionIsRendering && renderSection.canRender())
|
||||||
|
{
|
||||||
|
// if rendering is already enabled we don't have to re-enable it
|
||||||
|
if (!renderSection.getRenderingEnabled())
|
||||||
{
|
{
|
||||||
nodesNeedingLoading.add(renderSection);
|
renderSection.setRenderingEnabled(true);
|
||||||
}
|
|
||||||
|
// disabling rendering must be done after the parent is enabled
|
||||||
if (Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus.get())
|
// otherwise holes may appear in the world, overlaps are less noticeable
|
||||||
{
|
quadNode.deleteAllChildren((childRenderSection) ->
|
||||||
this.debugRenderSections.add(renderSection);
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for the parent to disable before enabling this section, so we don't overdraw/overlap render sections
|
|
||||||
if (!parentSectionIsRendering && renderSection.canRender())
|
|
||||||
{
|
|
||||||
// if rendering is already enabled we don't have to re-enable it
|
|
||||||
if (!renderSection.getRenderingEnabled())
|
|
||||||
{
|
{
|
||||||
// delete/disable children, all of them will be a lower detail level than requested
|
if (childRenderSection != null)
|
||||||
quadNode.deleteAllChildren((childRenderSection) ->
|
|
||||||
{
|
{
|
||||||
if (childRenderSection != null)
|
if (childRenderSection.getRenderingEnabled())
|
||||||
{
|
{
|
||||||
if (childRenderSection.getRenderingEnabled())
|
// this position's rendering has been disabled due to a parent rendering
|
||||||
{
|
DebugRenderer.makeParticle(new DebugRenderer.BoxParticle(new DebugRenderer.Box(childRenderSection.pos, 128f, 156f, 0.09f, Color.MAGENTA),0.2, 32f));
|
||||||
// show that this position's rendering has been disabled due to a parent rendering
|
|
||||||
DebugRenderer.makeParticle(
|
|
||||||
new DebugRenderer.BoxParticle(
|
|
||||||
new DebugRenderer.Box(childRenderSection.pos, 128f, 156f, 0.09f, Color.MAGENTA.darker()),
|
|
||||||
0.2, 32f
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
childRenderSection.setRenderingEnabled(false);
|
|
||||||
childRenderSection.close();
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
childRenderSection.setRenderingEnabled(false);
|
||||||
renderSection.setRenderingEnabled(true);
|
childRenderSection.onRenderingDisabled();
|
||||||
}
|
childRenderSection.close();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if (!renderSection.isFullyGenerated())
|
|
||||||
{
|
// onRenderingEnabled() needs to be fired after the children are disabled so beacons render correctly
|
||||||
nodesNeedingRetrieval.add(renderSection);
|
renderSection.onRenderingEnabled();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// renderSection.disableRendering();
|
|
||||||
//}
|
|
||||||
|
|
||||||
return renderSection.canRender();
|
return renderSection.canRender();
|
||||||
}
|
}
|
||||||
@@ -591,12 +585,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//==================//
|
|
||||||
// config listeners //
|
|
||||||
//==================//
|
|
||||||
|
|
||||||
private void onHorizontalQualityChange() { /*this.clearRenderDataCache();*/ }
|
|
||||||
|
|
||||||
|
|
||||||
//===========//
|
//===========//
|
||||||
// debugging //
|
// debugging //
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.enums.EDhDirection;
|
|||||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
||||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||||
@@ -393,37 +393,35 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
public boolean canRender() { return this.canRender; }
|
public boolean canRender() { return this.canRender; }
|
||||||
|
|
||||||
public boolean getRenderingEnabled() { return this.renderingEnabled; }
|
public boolean getRenderingEnabled() { return this.renderingEnabled; }
|
||||||
public void setRenderingEnabled(boolean enabled)
|
/**
|
||||||
|
* Separate from {@link LodRenderSection#onRenderingEnabled} and {@link LodRenderSection#onRenderingDisabled}
|
||||||
|
* since we need to trigger external changes in disabled -> enabled order
|
||||||
|
* so beacons are removed and then re-added.
|
||||||
|
* However, to prevent holes in the world when disabling sections we need to
|
||||||
|
* enable the new section(s) first before disabling the old one(s).
|
||||||
|
*/
|
||||||
|
public void setRenderingEnabled(boolean enabled) { this.renderingEnabled = enabled;}
|
||||||
|
|
||||||
|
/** @see LodRenderSection#setRenderingEnabled */
|
||||||
|
public void onRenderingEnabled() { this.level.loadBeaconBeamsInPos(this.pos); }
|
||||||
|
/** @see LodRenderSection#setRenderingEnabled */
|
||||||
|
public void onRenderingDisabled()
|
||||||
{
|
{
|
||||||
// some logic should only be run when enabling/disabling
|
this.level.unloadBeaconBeamsInPos(this.pos);
|
||||||
// a section for the first time
|
|
||||||
boolean stateChanged = (this.renderingEnabled != enabled);
|
|
||||||
if (stateChanged)
|
|
||||||
{
|
|
||||||
if (enabled)
|
|
||||||
{
|
|
||||||
this.level.loadBeaconBeamsInPos(this.pos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.level.unloadBeaconBeamsInPos(this.pos);
|
|
||||||
|
|
||||||
if (Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.get())
|
|
||||||
{
|
|
||||||
// show that this position has just been disabled
|
|
||||||
DebugRenderer.makeParticle(
|
|
||||||
new DebugRenderer.BoxParticle(
|
|
||||||
new DebugRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.CYAN.darker()),
|
|
||||||
0.2, 32f
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.renderingEnabled = enabled;
|
if (Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.get())
|
||||||
|
{
|
||||||
|
// show that this position has just been disabled
|
||||||
|
DebugRenderer.makeParticle(
|
||||||
|
new DebugRenderer.BoxParticle(
|
||||||
|
new DebugRenderer.Box(this.pos, 128f, 156f, 0.09f, Color.CYAN.darker()),
|
||||||
|
0.2, 32f
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean gpuUploadInProgress() { return this.buildAndUploadRenderDataToGpuFuture != null; }
|
public boolean gpuUploadInProgress() { return this.buildAndUploadRenderDataToGpuFuture != null; }
|
||||||
|
|
||||||
|
|
||||||
@@ -505,9 +503,9 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
|||||||
@Override
|
@Override
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
return "LodRenderSection{" +
|
return "pos=[" + DhSectionPos.toString(this.pos) + "] " +
|
||||||
"pos=" + this.pos +
|
"enabled=[" + this.renderingEnabled + "] " +
|
||||||
'}';
|
"uploading=[" + this.gpuUploadInProgress() + "] ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -195,11 +195,11 @@ public class RenderBufferHandler implements AutoCloseable
|
|||||||
int abPosDifference;
|
int abPosDifference;
|
||||||
if (axisDirection.getAxis().equals(EDhDirection.Axis.X))
|
if (axisDirection.getAxis().equals(EDhDirection.Axis.X))
|
||||||
{
|
{
|
||||||
abPosDifference = aPos.x - bPos.x;
|
abPosDifference = aPos.getX() - bPos.getX();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
abPosDifference = aPos.y - bPos.y;
|
abPosDifference = aPos.getY() - bPos.getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (abPosDifference == 0)
|
if (abPosDifference == 0)
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
|||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||||
@@ -475,7 +475,7 @@ public class LodRenderer
|
|||||||
public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException
|
public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException
|
||||||
{
|
{
|
||||||
Vec3d cam = MC_RENDER.getCameraExactPosition();
|
Vec3d cam = MC_RENDER.getCameraExactPosition();
|
||||||
Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z));
|
Vec3f modelPos = new Vec3f((float) (pos.getX() - cam.x), (float) (pos.getY() - cam.y), (float) (pos.getZ() - cam.z));
|
||||||
|
|
||||||
|
|
||||||
IDhApiShaderProgram shaderProgram = this.lodRenderProgram;
|
IDhApiShaderProgram shaderProgram = this.lodRenderProgram;
|
||||||
|
|||||||
+174
-42
@@ -21,17 +21,20 @@ package com.seibel.distanthorizons.core.render.renderer.generic;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||||
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
|
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@@ -41,6 +44,10 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class BeaconRenderHandler
|
public class BeaconRenderHandler
|
||||||
{
|
{
|
||||||
@@ -49,13 +56,23 @@ public class BeaconRenderHandler
|
|||||||
|
|
||||||
private static final int BEAM_TOP_Y = 6_000;
|
private static final int BEAM_TOP_Y = 6_000;
|
||||||
|
|
||||||
|
/** how often should we check if a beacon should be culled? */
|
||||||
|
private static final int MAX_CULLING_FREQUENCY_IN_MS = 1_000;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** if this is null then the other handler is probably null too, but just in case */
|
/** if this is null then the other handler is probably null too, but just in case */
|
||||||
private final BeaconBeamRepo beaconBeamRepo;
|
private final BeaconBeamRepo beaconBeamRepo;
|
||||||
|
|
||||||
|
private final ReentrantLock updateLock = new ReentrantLock();
|
||||||
|
|
||||||
private final IDhApiRenderableBoxGroup beaconBoxGroup;
|
private final IDhApiRenderableBoxGroup beaconBoxGroup;
|
||||||
|
private final ArrayList<DhApiRenderableBox> fullBeaconBoxList = new ArrayList<>();
|
||||||
private final HashSet<DhBlockPos> beaconBlockPosSet = new HashSet<>();
|
private final HashSet<DhBlockPos> beaconBlockPosSet = new HashSet<>();
|
||||||
|
|
||||||
|
private boolean cullingThreadRunning = false;
|
||||||
|
private boolean updateRenderDataNextFrame = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//=============//
|
//=============//
|
||||||
@@ -71,7 +88,7 @@ public class BeaconRenderHandler
|
|||||||
this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||||
this.beaconBoxGroup.setSsaoEnabled(false);
|
this.beaconBoxGroup.setSsaoEnabled(false);
|
||||||
this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded());
|
this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded());
|
||||||
this.beaconBoxGroup.setPreRenderFunc((renderEventParam) -> this.beaconBoxGroup.setActive(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering.get()));
|
this.beaconBoxGroup.setPreRenderFunc(this::beforeRender);
|
||||||
|
|
||||||
renderer.add(this.beaconBoxGroup);
|
renderer.add(this.beaconBoxGroup);
|
||||||
}
|
}
|
||||||
@@ -82,7 +99,7 @@ public class BeaconRenderHandler
|
|||||||
// level loading/unloading //
|
// level loading/unloading //
|
||||||
//=========================//
|
//=========================//
|
||||||
|
|
||||||
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> newBeamList)
|
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> activeBeamList)
|
||||||
{
|
{
|
||||||
// synchronized to prevent two threads from updating the same chunk at the same time
|
// synchronized to prevent two threads from updating the same chunk at the same time
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
@@ -90,11 +107,11 @@ public class BeaconRenderHandler
|
|||||||
HashSet<DhBlockPos> allPosSet = new HashSet<>();
|
HashSet<DhBlockPos> allPosSet = new HashSet<>();
|
||||||
|
|
||||||
// sort new beams
|
// sort new beams
|
||||||
HashMap<DhBlockPos, BeaconBeamDTO> newBeamByPos = new HashMap<>(newBeamList.size());
|
HashMap<DhBlockPos, BeaconBeamDTO> activeBeamByPos = new HashMap<>(activeBeamList.size());
|
||||||
for (int i = 0; i < newBeamList.size(); i++)
|
for (int i = 0; i < activeBeamList.size(); i++)
|
||||||
{
|
{
|
||||||
BeaconBeamDTO beam = newBeamList.get(i);
|
BeaconBeamDTO beam = activeBeamList.get(i);
|
||||||
newBeamByPos.put(beam.blockPos, beam);
|
activeBeamByPos.put(beam.blockPos, beam);
|
||||||
allPosSet.add(beam.blockPos);
|
allPosSet.add(beam.blockPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,28 +136,28 @@ public class BeaconRenderHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos);
|
BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos);
|
||||||
BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos);
|
BeaconBeamDTO activeBeam = activeBeamByPos.get(beaconPos);
|
||||||
|
|
||||||
if (existingBeam != null && newBeam != null)
|
if (existingBeam != null && activeBeam != null)
|
||||||
{
|
{
|
||||||
// beam still exists in chunk
|
// beam still exists in chunk
|
||||||
if (!existingBeam.color.equals(newBeam.color))
|
if (!existingBeam.color.equals(activeBeam.color))
|
||||||
{
|
{
|
||||||
// beam colors were changed
|
// beam colors were changed
|
||||||
this.beaconBeamRepo.save(newBeam);
|
this.beaconBeamRepo.save(activeBeam);
|
||||||
this.updateBeaconColor(newBeam);
|
this.updateBeaconColor(activeBeam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (existingBeam == null && newBeam != null)
|
else if (existingBeam == null && activeBeam != null)
|
||||||
{
|
{
|
||||||
// new beam found, add to DB
|
// new beam found, add to DB
|
||||||
this.beaconBeamRepo.save(newBeam);
|
this.beaconBeamRepo.save(activeBeam);
|
||||||
this.startRenderingBeacon(newBeam);
|
this.startRenderingBeacon(activeBeam);
|
||||||
}
|
}
|
||||||
else if (existingBeam != null && newBeam == null)
|
else if (existingBeam != null && activeBeam == null)
|
||||||
{
|
{
|
||||||
// beam no longer exists at position, remove from DB
|
// beam no longer exists at position, remove from DB
|
||||||
this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks
|
this.beaconBeamRepo.deleteWithKey(beaconPos);
|
||||||
this.stopRenderingBeaconAtPos(beaconPos);
|
this.stopRenderingBeaconAtPos(beaconPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,49 +195,164 @@ public class BeaconRenderHandler
|
|||||||
|
|
||||||
private void startRenderingBeacon(BeaconBeamDTO beacon)
|
private void startRenderingBeacon(BeaconBeamDTO beacon)
|
||||||
{
|
{
|
||||||
if (this.beaconBlockPosSet.add(beacon.blockPos))
|
try
|
||||||
{
|
{
|
||||||
DhApiRenderableBox beaconBox = new DhApiRenderableBox(
|
this.updateLock.lock();
|
||||||
new DhApiVec3d(beacon.blockPos.x, beacon.blockPos.y+1, beacon.blockPos.z),
|
|
||||||
new DhApiVec3d(beacon.blockPos.x+1, BEAM_TOP_Y, beacon.blockPos.z+1),
|
|
||||||
beacon.color,
|
|
||||||
EDhApiBlockMaterial.ILLUMINATED
|
|
||||||
);
|
|
||||||
|
|
||||||
this.beaconBoxGroup.add(beaconBox);
|
if (this.beaconBlockPosSet.add(beacon.blockPos))
|
||||||
this.beaconBoxGroup.triggerBoxChange();
|
{
|
||||||
|
DhApiRenderableBox beaconBox = new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(beacon.blockPos.getX(), beacon.blockPos.getY() + 1, beacon.blockPos.getZ()),
|
||||||
|
new DhApiVec3d(beacon.blockPos.getX() + 1, BEAM_TOP_Y, beacon.blockPos.getZ() + 1),
|
||||||
|
beacon.color,
|
||||||
|
EDhApiBlockMaterial.ILLUMINATED
|
||||||
|
);
|
||||||
|
|
||||||
|
this.beaconBoxGroup.add(beaconBox);
|
||||||
|
this.fullBeaconBoxList.add(beaconBox);
|
||||||
|
this.beaconBoxGroup.triggerBoxChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.updateLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void stopRenderingBeaconAtPos(DhBlockPos beaconPos)
|
private void stopRenderingBeaconAtPos(DhBlockPos beaconPos)
|
||||||
{
|
{
|
||||||
if (this.beaconBlockPosSet.remove(beaconPos))
|
try
|
||||||
{
|
{
|
||||||
this.beaconBoxGroup.removeIf((box) ->
|
this.updateLock.lock();
|
||||||
|
|
||||||
|
if (this.beaconBlockPosSet.remove(beaconPos))
|
||||||
{
|
{
|
||||||
return box.minPos.x == beaconPos.x
|
Predicate<DhApiRenderableBox> removePredicate = (DhApiRenderableBox box) ->
|
||||||
&& box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon
|
{
|
||||||
&& box.minPos.z == beaconPos.z;
|
return box.minPos.x == beaconPos.getX()
|
||||||
});
|
&& box.minPos.y == beaconPos.getY() + 1 // plus 1 because the beam starts above the beacon
|
||||||
this.beaconBoxGroup.triggerBoxChange();
|
&& box.minPos.z == beaconPos.getZ();
|
||||||
|
};
|
||||||
|
this.beaconBoxGroup.removeIf(removePredicate);
|
||||||
|
this.fullBeaconBoxList.removeIf(removePredicate);
|
||||||
|
|
||||||
|
this.beaconBoxGroup.triggerBoxChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.updateLock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBeaconColor(BeaconBeamDTO newBeam)
|
private void updateBeaconColor(BeaconBeamDTO newBeam)
|
||||||
{
|
{
|
||||||
DhBlockPos pos = newBeam.blockPos;
|
try
|
||||||
for (int i = 0; i < this.beaconBoxGroup.size(); i++)
|
|
||||||
{
|
{
|
||||||
DhApiRenderableBox box = this.beaconBoxGroup.get(i);
|
this.updateLock.lock();
|
||||||
if (box.minPos.x == pos.x
|
|
||||||
&& box.minPos.y == pos.y+1 // plus 1 because the beam starts above the beacon
|
DhBlockPos pos = newBeam.blockPos;
|
||||||
&& box.minPos.z == pos.z)
|
for (int i = 0; i < this.fullBeaconBoxList.size(); i++)
|
||||||
{
|
{
|
||||||
box.color = newBeam.color;
|
DhApiRenderableBox box = this.fullBeaconBoxList.get(i);
|
||||||
this.beaconBoxGroup.triggerBoxChange();
|
if (box.minPos.x == pos.getX()
|
||||||
break;
|
&& box.minPos.y == pos.getY() + 1 // plus 1 because the beam starts above the beacon
|
||||||
|
&& box.minPos.z == pos.getZ())
|
||||||
|
{
|
||||||
|
box.color = newBeam.color;
|
||||||
|
this.beaconBoxGroup.triggerBoxChange();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.updateLock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void beforeRender(DhApiRenderParam renderEventParam)
|
||||||
|
{
|
||||||
|
if (!Config.Client.Advanced.Graphics.AdvancedGraphics.disableBeaconDistanceCulling.get())
|
||||||
|
{
|
||||||
|
// this could be called only when the player moves, but it's an extremely cheap check,
|
||||||
|
// so there isn't much of a reason to bother
|
||||||
|
this.tryUpdateBeaconCullingAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// this must be called on the render thread to prevent concurrency issues
|
||||||
|
if (this.updateRenderDataNextFrame)
|
||||||
|
{
|
||||||
|
this.beaconBoxGroup.triggerBoxChange();
|
||||||
|
this.updateRenderDataNextFrame = false;
|
||||||
|
}
|
||||||
|
this.beaconBoxGroup.setActive(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering.get());
|
||||||
|
}
|
||||||
|
/** does nothing if the culling thread is already running */
|
||||||
|
private void tryUpdateBeaconCullingAsync()
|
||||||
|
{
|
||||||
|
ThreadPoolExecutor executor = ThreadPoolUtil.getBeaconCullingExecutor();
|
||||||
|
if (executor != null
|
||||||
|
&& !this.cullingThreadRunning)
|
||||||
|
{
|
||||||
|
this.cullingThreadRunning = true;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
executor.execute(() ->
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(MAX_CULLING_FREQUENCY_IN_MS);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore) { }
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// lock to make sure we don't try adding beacons to the arrays while processing them
|
||||||
|
this.updateLock.lock();
|
||||||
|
|
||||||
|
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
|
||||||
|
double mcRenderDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
|
||||||
|
|
||||||
|
|
||||||
|
// Clear the existing box group so we can re-populate it.
|
||||||
|
// Since the box group is only used when we trigger an update, clearing it here
|
||||||
|
// and repopulating it is fine.
|
||||||
|
this.beaconBoxGroup.clear();
|
||||||
|
|
||||||
|
// While iterating over every beacon isn't a great way of doing this,
|
||||||
|
// when 940 beacons were tested this only took ~0.9 Milliseconds, so as long as
|
||||||
|
// we aren't freezing the render thread this method of culling works just fine.
|
||||||
|
for (DhApiRenderableBox box : this.fullBeaconBoxList)
|
||||||
|
{
|
||||||
|
// if a beacon is outside the vanilla render distance render it
|
||||||
|
double distance = Vec3d.getHorizontalDistance(cameraPos, box.minPos);
|
||||||
|
if (distance > mcRenderDistance)
|
||||||
|
{
|
||||||
|
this.beaconBoxGroup.add(box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateRenderDataNextFrame = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOGGER.error("Unexpected issue while updating beacon culling. Error: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.updateLock.unlock();
|
||||||
|
this.cullingThreadRunning = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (RejectedExecutionException ignore)
|
||||||
|
{ /* If this happens that means everything is already shut down and no culling is necessary */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-31
@@ -21,12 +21,14 @@ package com.seibel.distanthorizons.core.render.renderer.generic;
|
|||||||
|
|
||||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
@@ -48,8 +50,6 @@ public class CloudRenderHandler
|
|||||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
private static final String CLOUD_RESOURCE_TEXTURE_PATH = "assets/distanthorizons/textures/clouds.png";
|
private static final String CLOUD_RESOURCE_TEXTURE_PATH = "assets/distanthorizons/textures/clouds.png";
|
||||||
// FIXME transparency sorting makes having transparent clouds impossible
|
|
||||||
private static final Color CLOUD_COLOR = new Color(255,255,255,255);
|
|
||||||
|
|
||||||
private static final boolean DEBUG_BORDER_COLORS = false;
|
private static final boolean DEBUG_BORDER_COLORS = false;
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ public class CloudRenderHandler
|
|||||||
private static final int CLOUD_BOX_THICKNESS = 16;
|
private static final int CLOUD_BOX_THICKNESS = 16;
|
||||||
|
|
||||||
private final IDhApiRenderableBoxGroup[][] boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3];
|
private final IDhApiRenderableBoxGroup[][] boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3];
|
||||||
private final IDhLevel level;
|
private final IDhClientLevel level;
|
||||||
private final GenericObjectRenderer renderer;
|
private final GenericObjectRenderer renderer;
|
||||||
|
|
||||||
private float moveSpeedInBlocksPerSecond = 3.0f;
|
private float moveSpeedInBlocksPerSecond = 3.0f;
|
||||||
@@ -74,7 +74,7 @@ public class CloudRenderHandler
|
|||||||
// constructor //
|
// constructor //
|
||||||
//=============//
|
//=============//
|
||||||
|
|
||||||
public CloudRenderHandler(IDhLevel level, GenericObjectRenderer renderer)
|
public CloudRenderHandler(IDhClientLevel level, GenericObjectRenderer renderer)
|
||||||
{
|
{
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
@@ -195,16 +195,8 @@ public class CloudRenderHandler
|
|||||||
int maxXBlockPos = endX * CLOUD_BOX_WIDTH;
|
int maxXBlockPos = endX * CLOUD_BOX_WIDTH;
|
||||||
int maxZBlockPos = endZ * CLOUD_BOX_WIDTH;
|
int maxZBlockPos = endZ * CLOUD_BOX_WIDTH;
|
||||||
|
|
||||||
Color color = CLOUD_COLOR;
|
// this color is changed at render time based on the level time
|
||||||
if (DEBUG_BORDER_COLORS)
|
Color color = new Color(255,255,255,255);
|
||||||
{
|
|
||||||
// equals is included so the board is 2 blocks wide, it makes it easier to see
|
|
||||||
if (startX <= 1) { color = Color.RED; }
|
|
||||||
else if (startX >= textureWidth - 2) { color = Color.GREEN; }
|
|
||||||
if (startZ <= 1) { color = Color.BLUE; }
|
|
||||||
else if (endZ >= textureWidth - 2) { color = Color.BLACK; }
|
|
||||||
}
|
|
||||||
|
|
||||||
DhApiRenderableBox box = new DhApiRenderableBox(
|
DhApiRenderableBox box = new DhApiRenderableBox(
|
||||||
new DhApiVec3d(minXBlockPos, 0, minZBlockPos),
|
new DhApiVec3d(minXBlockPos, 0, minZBlockPos),
|
||||||
new DhApiVec3d(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos),
|
new DhApiVec3d(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos),
|
||||||
@@ -238,13 +230,15 @@ public class CloudRenderHandler
|
|||||||
ModInfo.NAME + ":Clouds",
|
ModInfo.NAME + ":Clouds",
|
||||||
new DhApiVec3d(0, 0, 0), // the offset will be set during rendering
|
new DhApiVec3d(0, 0, 0), // the offset will be set during rendering
|
||||||
boxList);
|
boxList);
|
||||||
boxGroup.setBlockLight(LodUtil.MIN_MC_LIGHT);
|
|
||||||
|
// since cloud colors are set by the level based on the time of day lighting should affect it
|
||||||
|
boxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||||
boxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
boxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||||
boxGroup.setSsaoEnabled(false);
|
boxGroup.setSsaoEnabled(false);
|
||||||
boxGroup.setShading(cloudShading);
|
boxGroup.setShading(cloudShading);
|
||||||
|
|
||||||
CloudParams params = new CloudParams(textureWidth, x, z);
|
CloudParams cloudParams = new CloudParams(textureWidth, x, z);
|
||||||
boxGroup.setPreRenderFunc((renderParam) -> this.preRender(params));
|
boxGroup.setPreRenderFunc((renderParam) -> this.preRender(renderParam, cloudParams));
|
||||||
|
|
||||||
renderer.add(boxGroup);
|
renderer.add(boxGroup);
|
||||||
this.boxGroupByOffset[x+1][z+1] = boxGroup;
|
this.boxGroupByOffset[x+1][z+1] = boxGroup;
|
||||||
@@ -252,9 +246,15 @@ public class CloudRenderHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void preRender(CloudParams clouds)
|
private void preRender(DhApiRenderParam renderParam, CloudParams cloudParams)
|
||||||
{
|
{
|
||||||
IDhApiRenderableBoxGroup boxGroup = this.boxGroupByOffset[clouds.instanceOffsetX+1][clouds.instanceOffsetZ+1];
|
IDhApiRenderableBoxGroup boxGroup = this.boxGroupByOffset[cloudParams.instanceOffsetX+1][cloudParams.instanceOffsetZ+1];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// should we render? //
|
||||||
|
//===================//
|
||||||
|
|
||||||
boolean renderClouds = Config.Client.Advanced.Graphics.GenericRendering.enableCloudRendering.get();
|
boolean renderClouds = Config.Client.Advanced.Graphics.GenericRendering.enableCloudRendering.get();
|
||||||
boxGroup.setActive(renderClouds);
|
boxGroup.setActive(renderClouds);
|
||||||
@@ -275,19 +275,46 @@ public class CloudRenderHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// cloud color //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
// FIXME transparency sorting makes having transparent clouds impossible
|
||||||
|
// maybe someday we could add the option to cull individual faces? a single bit for each direction should be enough
|
||||||
|
|
||||||
|
// cloud color changes based on the time of day and weather so we need to get it from the level
|
||||||
|
Color cloudColor = this.level.getClientLevelWrapper().getCloudColor(renderParam.partialTicks);
|
||||||
|
if (DEBUG_BORDER_COLORS)
|
||||||
|
{
|
||||||
|
// equals is included so the board is 2 blocks wide, it makes it easier to see
|
||||||
|
if (cloudParams.instanceOffsetX <= 1) { cloudColor = Color.RED; }
|
||||||
|
else if (cloudParams.instanceOffsetX >= cloudParams.textureWidth - 2) { cloudColor = Color.GREEN; }
|
||||||
|
if (cloudParams.instanceOffsetZ <= 1) { cloudColor = Color.BLUE; }
|
||||||
|
else if (cloudParams.instanceOffsetZ >= cloudParams.textureWidth - 2) { cloudColor = Color.BLACK; }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DhApiRenderableBox box : boxGroup)
|
||||||
|
{
|
||||||
|
box.color = cloudColor;
|
||||||
|
}
|
||||||
|
boxGroup.triggerBoxChange();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//================//
|
//================//
|
||||||
// cloud movement //
|
// cloud movement //
|
||||||
//================//
|
//================//
|
||||||
|
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
float deltaTime = (currentTime - clouds.lastFrameTime) / 1000.0f; // Delta time in seconds
|
float deltaTime = (currentTime - cloudParams.lastFrameTime) / 1000.0f; // Delta time in seconds
|
||||||
clouds.lastFrameTime = currentTime;
|
cloudParams.lastFrameTime = currentTime;
|
||||||
|
|
||||||
float deltaX = this.moveSpeedInBlocksPerSecond * deltaTime;
|
float deltaX = this.moveSpeedInBlocksPerSecond * deltaTime;
|
||||||
// negative delta is to match vanilla's cloud movement
|
// negative delta is to match vanilla's cloud movement
|
||||||
clouds.xOffset -= deltaX;
|
cloudParams.xOffset -= deltaX;
|
||||||
// wrap the cloud around after reaching the edge
|
// wrap the cloud around after reaching the edge
|
||||||
clouds.xOffset %= clouds.widthInBlocks;
|
cloudParams.xOffset %= cloudParams.widthInBlocks;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -299,16 +326,16 @@ public class CloudRenderHandler
|
|||||||
int cameraPosX = (int)MC_RENDER.getCameraExactPosition().x;
|
int cameraPosX = (int)MC_RENDER.getCameraExactPosition().x;
|
||||||
int cameraPosZ = (int)MC_RENDER.getCameraExactPosition().z;
|
int cameraPosZ = (int)MC_RENDER.getCameraExactPosition().z;
|
||||||
// offset the camera position by negative 1 width when below zero to fix off-by-one errors in the negative direction
|
// offset the camera position by negative 1 width when below zero to fix off-by-one errors in the negative direction
|
||||||
if (cameraPosX < 0) { cameraPosX -= clouds.widthInBlocks; }
|
if (cameraPosX < 0) { cameraPosX -= (int)cloudParams.widthInBlocks; }
|
||||||
if (cameraPosZ < 0) { cameraPosZ -= clouds.widthInBlocks; }
|
if (cameraPosZ < 0) { cameraPosZ -= (int)cloudParams.widthInBlocks; }
|
||||||
|
|
||||||
// determine how many cloud instances away from the origin we are
|
// determine how many cloud instances away from the origin we are
|
||||||
int cloudInstanceOffsetX = cameraPosX / (int)clouds.widthInBlocks;
|
int cloudInstanceOffsetX = cameraPosX / (int)cloudParams.widthInBlocks;
|
||||||
int cloudInstanceOffsetZ = cameraPosZ / (int)clouds.widthInBlocks;
|
int cloudInstanceOffsetZ = cameraPosZ / (int)cloudParams.widthInBlocks;
|
||||||
|
|
||||||
// calculate the new offset
|
// calculate the new offset
|
||||||
float xOffset = (cloudInstanceOffsetX * clouds.widthInBlocks);
|
float xOffset = (cloudInstanceOffsetX * cloudParams.widthInBlocks);
|
||||||
float zOffset = (cloudInstanceOffsetZ * clouds.widthInBlocks);
|
float zOffset = (cloudInstanceOffsetZ * cloudParams.widthInBlocks);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -318,9 +345,9 @@ public class CloudRenderHandler
|
|||||||
|
|
||||||
boxGroup.setOriginBlockPos(
|
boxGroup.setOriginBlockPos(
|
||||||
new DhApiVec3d(
|
new DhApiVec3d(
|
||||||
clouds.xOffset + (clouds.instanceOffsetX * clouds.widthInBlocks) + xOffset + clouds.halfWidthInBlocks,
|
cloudParams.xOffset + (cloudParams.instanceOffsetX * cloudParams.widthInBlocks) + xOffset + cloudParams.halfWidthInBlocks,
|
||||||
this.level.getLevelWrapper().getMaxHeight() + 200,
|
this.level.getLevelWrapper().getMaxHeight() + 200,
|
||||||
clouds.zOffset + (clouds.instanceOffsetZ * clouds.widthInBlocks) + zOffset + clouds.halfWidthInBlocks
|
cloudParams.zOffset + (cloudParams.instanceOffsetZ * cloudParams.widthInBlocks) + zOffset + cloudParams.halfWidthInBlocks
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-2
@@ -30,7 +30,9 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
|
|||||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||||
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
@@ -42,11 +44,14 @@ import com.seibel.distanthorizons.core.util.LodUtil;
|
|||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccessor;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
import org.lwjgl.opengl.ARBInstancedArrays;
|
import org.lwjgl.opengl.ARBInstancedArrays;
|
||||||
import org.lwjgl.opengl.GL32;
|
import org.lwjgl.opengl.GL32;
|
||||||
import org.lwjgl.opengl.GL33;
|
import org.lwjgl.opengl.GL33;
|
||||||
@@ -70,6 +75,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
|
|||||||
public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(GenericObjectRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1);
|
public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(GenericObjectRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1);
|
||||||
|
|
||||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
private static final ISodiumAccessor SODIUM = ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can be used to troubleshoot the renderer.
|
* Can be used to troubleshoot the renderer.
|
||||||
@@ -172,17 +178,37 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister
|
|||||||
}
|
}
|
||||||
this.init = true;
|
this.init = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================//
|
||||||
|
// is instanced rendering available? //
|
||||||
|
//===================================//
|
||||||
|
|
||||||
this.vertexAttribDivisorSupported = GLProxy.getInstance().vertexAttribDivisorSupported;
|
this.vertexAttribDivisorSupported = GLProxy.getInstance().vertexAttribDivisorSupported;
|
||||||
this.instancedArraysSupported = GLProxy.getInstance().instancedArraysSupported;
|
this.instancedArraysSupported = GLProxy.getInstance().instancedArraysSupported;
|
||||||
this.useInstancedRendering = this.vertexAttribDivisorSupported || this.instancedArraysSupported;
|
this.useInstancedRendering = this.vertexAttribDivisorSupported || this.instancedArraysSupported;
|
||||||
if (!this.useInstancedRendering)
|
if (!this.useInstancedRendering)
|
||||||
{
|
{
|
||||||
LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering will be slow.");
|
LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering will be slow and some effects may be disabled.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boolean isMac = (EPlatform.get() == EPlatform.MACOS);
|
||||||
|
if (isMac && SODIUM != null)
|
||||||
|
{
|
||||||
|
this.useInstancedRendering = false;
|
||||||
|
LOGGER.warn("Instanced rendering is broken on Mac when Sodium is present, falling back to direct rendering. Generic object rendering will be slow and some effects may be disabled.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.shaderProgram = new GenericObjectShaderProgram(this.useInstancedRendering);
|
|
||||||
|
|
||||||
|
|
||||||
|
//======================//
|
||||||
|
// startup the renderer //
|
||||||
|
//======================//
|
||||||
|
|
||||||
|
this.shaderProgram = new GenericObjectShaderProgram(this.useInstancedRendering);
|
||||||
|
|
||||||
this.createBuffers();
|
this.createBuffers();
|
||||||
|
|
||||||
if (RENDER_DEBUG_OBJECTS)
|
if (RENDER_DEBUG_OBJECTS)
|
||||||
|
|||||||
+2
-1
@@ -215,7 +215,8 @@ public class RenderableBoxGroup
|
|||||||
public Stream<DhApiRenderableBox> stream() { return this.boxList.stream(); }
|
public Stream<DhApiRenderableBox> stream() { return this.boxList.stream(); }
|
||||||
@Override
|
@Override
|
||||||
public Stream<DhApiRenderableBox> parallelStream() { return this.boxList.parallelStream(); }
|
public Stream<DhApiRenderableBox> parallelStream() { return this.boxList.parallelStream(); }
|
||||||
|
@Override
|
||||||
|
public void clear() { this.boxList.clear(); }
|
||||||
|
|
||||||
|
|
||||||
//===================//
|
//===================//
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.core.sql.dto;
|
package com.seibel.distanthorizons.core.sql.dto;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.core.sql.repo;
|
package com.seibel.distanthorizons.core.sql.repo;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||||
@@ -60,7 +60,7 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
|
|||||||
public String getTableName() { return "BeaconBeam"; }
|
public String getTableName() { return "BeaconBeam"; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createWhereStatement(DhBlockPos pos) { return "BlockPosX = "+pos.x+" AND BlockPosY = "+pos.y+" AND BlockPosZ = "+pos.z; }
|
public String createWhereStatement(DhBlockPos pos) { return "BlockPosX = "+ pos.getX() +" AND BlockPosY = "+ pos.getY() +" AND BlockPosZ = "+ pos.getZ(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -100,9 +100,9 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
|
|||||||
PreparedStatement statement = this.createPreparedStatement(sql);
|
PreparedStatement statement = this.createPreparedStatement(sql);
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
statement.setObject(i++, dto.blockPos.x);
|
statement.setObject(i++, dto.blockPos.getX());
|
||||||
statement.setObject(i++, dto.blockPos.y);
|
statement.setObject(i++, dto.blockPos.getY());
|
||||||
statement.setObject(i++, dto.blockPos.z);
|
statement.setObject(i++, dto.blockPos.getZ());
|
||||||
|
|
||||||
statement.setObject(i++, dto.color.getRed());
|
statement.setObject(i++, dto.color.getRed());
|
||||||
statement.setObject(i++, dto.color.getGreen());
|
statement.setObject(i++, dto.color.getGreen());
|
||||||
@@ -132,9 +132,9 @@ public class BeaconBeamRepo extends AbstractDhRepo<DhBlockPos, BeaconBeamDTO>
|
|||||||
|
|
||||||
statement.setObject(i++, System.currentTimeMillis()); // last modified unix time
|
statement.setObject(i++, System.currentTimeMillis()); // last modified unix time
|
||||||
|
|
||||||
statement.setObject(i++, dto.blockPos.x);
|
statement.setObject(i++, dto.blockPos.getX());
|
||||||
statement.setObject(i++, dto.blockPos.y);
|
statement.setObject(i++, dto.blockPos.getY());
|
||||||
statement.setObject(i++, dto.blockPos.z);
|
statement.setObject(i++, dto.blockPos.getZ());
|
||||||
|
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,9 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.core.sql.repo;
|
package com.seibel.distanthorizons.core.sql.repo;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO;
|
import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -56,7 +54,7 @@ public class ChunkHashRepo extends AbstractDhRepo<DhChunkPos, ChunkHashDTO>
|
|||||||
public String getTableName() { return "ChunkHash"; }
|
public String getTableName() { return "ChunkHash"; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String createWhereStatement(DhChunkPos pos) { return "ChunkPosX = '"+pos.x+"' AND ChunkPosZ = '"+pos.z+"'"; }
|
public String createWhereStatement(DhChunkPos pos) { return "ChunkPosX = '"+ pos.getX() +"' AND ChunkPosZ = '"+ pos.getZ() +"'"; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -93,8 +91,8 @@ public class ChunkHashRepo extends AbstractDhRepo<DhChunkPos, ChunkHashDTO>
|
|||||||
PreparedStatement statement = this.createPreparedStatement(sql);
|
PreparedStatement statement = this.createPreparedStatement(sql);
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
statement.setObject(i++, dto.pos.x);
|
statement.setObject(i++, dto.pos.getX());
|
||||||
statement.setObject(i++, dto.pos.z);
|
statement.setObject(i++, dto.pos.getZ());
|
||||||
|
|
||||||
statement.setObject(i++, dto.chunkHash);
|
statement.setObject(i++, dto.chunkHash);
|
||||||
|
|
||||||
@@ -119,8 +117,8 @@ public class ChunkHashRepo extends AbstractDhRepo<DhChunkPos, ChunkHashDTO>
|
|||||||
statement.setObject(i++, dto.chunkHash);
|
statement.setObject(i++, dto.chunkHash);
|
||||||
statement.setObject(i++, System.currentTimeMillis()); // last modified unix time
|
statement.setObject(i++, System.currentTimeMillis()); // last modified unix time
|
||||||
|
|
||||||
statement.setObject(i++, dto.pos.x);
|
statement.setObject(i++, dto.pos.getX());
|
||||||
statement.setObject(i++, dto.pos.z);
|
statement.setObject(i++, dto.pos.getZ());
|
||||||
|
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,12 @@ import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
|||||||
import com.seibel.distanthorizons.core.config.Config;
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
|
||||||
import com.seibel.distanthorizons.core.world.IDhClientWorld;
|
import com.seibel.distanthorizons.core.world.IDhClientWorld;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,7 +140,7 @@ public class RenderUtil
|
|||||||
{
|
{
|
||||||
// if the player is a significant distance above the work, increase the
|
// if the player is a significant distance above the work, increase the
|
||||||
// near clip plane to fix Z imprecision issues
|
// near clip plane to fix Z imprecision issues
|
||||||
int playerHeight = MC.getPlayerBlockPos().y;
|
int playerHeight = MC.getPlayerBlockPos().getY();
|
||||||
int levelMaxHeight = level.getMaxHeight();
|
int levelMaxHeight = level.getMaxHeight();
|
||||||
if (playerHeight > levelMaxHeight + 1_000)
|
if (playerHeight > levelMaxHeight + 1_000)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -87,11 +87,11 @@ public class ArrayGridList<T> extends ArrayList<T>
|
|||||||
|
|
||||||
public final T get(Pos2D pos)
|
public final T get(Pos2D pos)
|
||||||
{
|
{
|
||||||
return get(pos.x, pos.y);
|
return get(pos.getX(), pos.getY());
|
||||||
}
|
}
|
||||||
public final T set(Pos2D pos, T e)
|
public final T set(Pos2D pos, T e)
|
||||||
{
|
{
|
||||||
return set(pos.x, pos.y, e);
|
return set(pos.getX(), pos.getY(), e);
|
||||||
}
|
}
|
||||||
public T get(int x, int y)
|
public T get(int x, int y)
|
||||||
{
|
{
|
||||||
|
|||||||
+32
-32
@@ -49,7 +49,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
// constructors //
|
// constructors //
|
||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
public MovableGridRingList(int halfWidth, Pos2D center) { this(halfWidth, center.x, center.y); }
|
public MovableGridRingList(int halfWidth, Pos2D center) { this(halfWidth, center.getX(), center.getY()); }
|
||||||
public MovableGridRingList(int halfWidth, int centerX, int centerY)
|
public MovableGridRingList(int halfWidth, int centerX, int centerY)
|
||||||
{
|
{
|
||||||
super((halfWidth * 2 + 1) * (halfWidth * 2 + 1));
|
super((halfWidth * 2 + 1) * (halfWidth * 2 + 1));
|
||||||
@@ -68,7 +68,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
//=====================//
|
//=====================//
|
||||||
|
|
||||||
/** see {@link MovableGridRingList#get(int, int)} for full documentation */
|
/** see {@link MovableGridRingList#get(int, int)} for full documentation */
|
||||||
public T get(Pos2D pos) { return this.get(pos.x, pos.y); }
|
public T get(Pos2D pos) { return this.get(pos.getX(), pos.getY()); }
|
||||||
/** returns null if x,y is outside the grid */
|
/** returns null if x,y is outside the grid */
|
||||||
public T get(int x, int y)
|
public T get(int x, int y)
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
|
|
||||||
|
|
||||||
/** see {@link MovableGridRingList#set(int, int, T)} for full documentation */
|
/** see {@link MovableGridRingList#set(int, int, T)} for full documentation */
|
||||||
public boolean set(Pos2D pos, T item) { return this.set(pos.x, pos.y, item); }
|
public boolean set(Pos2D pos, T item) { return this.set(pos.getX(), pos.getY(), item); }
|
||||||
/** returns false if x,y is outside the grid */
|
/** returns false if x,y is outside the grid */
|
||||||
public boolean set(int x, int y, T item)
|
public boolean set(int x, int y, T item)
|
||||||
{
|
{
|
||||||
@@ -132,7 +132,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** see {@link MovableGridRingList#setChained(int, int, T)} for full documentation */
|
/** see {@link MovableGridRingList#setChained(int, int, T)} for full documentation */
|
||||||
public T setChained(Pos2D pos, T item) { return this.setChained(pos.x, pos.y, item); }
|
public T setChained(Pos2D pos, T item) { return this.setChained(pos.getX(), pos.getY(), item); }
|
||||||
/**
|
/**
|
||||||
* returns null if x,y is outside the grid
|
* returns null if x,y is outside the grid
|
||||||
* Otherwise, returns the new value
|
* Otherwise, returns the new value
|
||||||
@@ -146,7 +146,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
//================//
|
//================//
|
||||||
|
|
||||||
/** see {@link MovableGridRingList#swap(int, int, T)} for full documentation */
|
/** see {@link MovableGridRingList#swap(int, int, T)} for full documentation */
|
||||||
public T swap(Pos2D pos, T item) { return this.swap(pos.x, pos.y, item); }
|
public T swap(Pos2D pos, T item) { return this.swap(pos.getX(), pos.getY(), item); }
|
||||||
/** returns the input item if x,y is outside the grid */
|
/** returns the input item if x,y is outside the grid */
|
||||||
public T swap(int x, int y, T item)
|
public T swap(int x, int y, T item)
|
||||||
{
|
{
|
||||||
@@ -178,7 +178,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
|
|
||||||
|
|
||||||
/** see {@link MovableGridRingList#remove(int, int)} for full documentation */
|
/** see {@link MovableGridRingList#remove(int, int)} for full documentation */
|
||||||
public T remove(Pos2D pos) { return this.remove(pos.x, pos.y); }
|
public T remove(Pos2D pos) { return this.remove(pos.getX(), pos.getY()); }
|
||||||
/** remove and return the item at x,y; returns null if the x,y are outside the grid */
|
/** remove and return the item at x,y; returns null if the x,y are outside the grid */
|
||||||
public T remove(int x, int y) { return this.swap(x, y, null); }
|
public T remove(int x, int y) { return this.swap(x, y, null); }
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
Pos2D cPos = this.minPosRef.get();
|
Pos2D cPos = this.minPosRef.get();
|
||||||
int newMinX = newCenterX - this.halfWidth;
|
int newMinX = newCenterX - this.halfWidth;
|
||||||
int newMinY = newCenterY - this.halfWidth;
|
int newMinY = newCenterY - this.halfWidth;
|
||||||
if (cPos.x == newMinX && cPos.y == newMinY)
|
if (cPos.getX() == newMinX && cPos.getY() == newMinY)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -239,8 +239,8 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
cPos = this.minPosRef.get();
|
cPos = this.minPosRef.get();
|
||||||
int deltaX = newMinX - cPos.x;
|
int deltaX = newMinX - cPos.getX();
|
||||||
int deltaY = newMinY - cPos.y;
|
int deltaY = newMinY - cPos.getY();
|
||||||
if (deltaX == 0 && deltaY == 0)
|
if (deltaX == 0 && deltaY == 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -259,14 +259,14 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
{
|
{
|
||||||
for (int y = 0; y < this.width; y++)
|
for (int y = 0; y < this.width; y++)
|
||||||
{
|
{
|
||||||
Pos2D itemPos = new Pos2D(x + cPos.x, y + cPos.y);
|
Pos2D itemPos = new Pos2D(x + cPos.getX(), y + cPos.getY());
|
||||||
|
|
||||||
if (x - deltaX < 0
|
if (x - deltaX < 0
|
||||||
|| y - deltaY < 0
|
|| y - deltaY < 0
|
||||||
|| x - deltaX >= this.width
|
|| x - deltaX >= this.width
|
||||||
|| y - deltaY >= this.width)
|
|| y - deltaY >= this.width)
|
||||||
{
|
{
|
||||||
T item = this._swapUnsafe(itemPos.x, itemPos.y, null);
|
T item = this._swapUnsafe(itemPos.getX(), itemPos.getY(), null);
|
||||||
if (item != null && removedItemConsumer != null)
|
if (item != null && removedItemConsumer != null)
|
||||||
{
|
{
|
||||||
removedItemConsumer.accept(item);
|
removedItemConsumer.accept(item);
|
||||||
@@ -300,10 +300,10 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
// position getters //
|
// position getters //
|
||||||
//==================//
|
//==================//
|
||||||
|
|
||||||
public Pos2D getCenter() { return new Pos2D(this.minPosRef.get().x + this.halfWidth, this.minPosRef.get().y + this.halfWidth); }
|
public Pos2D getCenter() { return new Pos2D(this.minPosRef.get().getX() + this.halfWidth, this.minPosRef.get().getY() + this.halfWidth); }
|
||||||
|
|
||||||
public Pos2D getMinPosInRange() { return this.minPosRef.get(); }
|
public Pos2D getMinPosInRange() { return this.minPosRef.get(); }
|
||||||
public Pos2D getMaxPosInRange() { return new Pos2D(this.minPosRef.get().x + this.width - 1, this.minPosRef.get().y + this.width - 1); }
|
public Pos2D getMaxPosInRange() { return new Pos2D(this.minPosRef.get().getX() + this.width - 1, this.minPosRef.get().getY() + this.width - 1); }
|
||||||
|
|
||||||
public int getWidth() { return this.width; }
|
public int getWidth() { return this.width; }
|
||||||
public int getHalfWidth() { return this.halfWidth; }
|
public int getHalfWidth() { return this.halfWidth; }
|
||||||
@@ -321,18 +321,18 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
public boolean inRange(int x, int y)
|
public boolean inRange(int x, int y)
|
||||||
{
|
{
|
||||||
Pos2D minPos = this.minPosRef.get();
|
Pos2D minPos = this.minPosRef.get();
|
||||||
return (x >= minPos.x
|
return (x >= minPos.getX()
|
||||||
&& x < minPos.x + this.width
|
&& x < minPos.getX() + this.width
|
||||||
&& y >= minPos.y
|
&& y >= minPos.getY()
|
||||||
&& y < minPos.y + this.width);
|
&& y < minPos.getY() + this.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean _inRangeAcquired(int x, int y, Pos2D min)
|
private boolean _inRangeAcquired(int x, int y, Pos2D min)
|
||||||
{
|
{
|
||||||
return (x >= min.x
|
return (x >= min.getX()
|
||||||
&& x < min.x + this.width
|
&& x < min.getX() + this.width
|
||||||
&& y >= min.y
|
&& y >= min.getY()
|
||||||
&& y < min.y + this.width);
|
&& y < min.getY() + this.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
private T _getUnsafe(int x, int y) { return super.get(Math.floorMod(x, this.width) + Math.floorMod(y, this.width) * this.width); }
|
private T _getUnsafe(int x, int y) { return super.get(Math.floorMod(x, this.width) + Math.floorMod(y, this.width) * this.width); }
|
||||||
@@ -379,9 +379,9 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Pos2D min = this.minPosRef.get();
|
Pos2D min = this.minPosRef.get();
|
||||||
for (int x = min.x; x < min.x + this.width; x++)
|
for (int x = min.getX(); x < min.getX() + this.width; x++)
|
||||||
{
|
{
|
||||||
for (int y = min.y; y < min.y + this.width; y++)
|
for (int y = min.getY(); y < min.getY() + this.width; y++)
|
||||||
{
|
{
|
||||||
T t = this._getUnsafe(x, y);
|
T t = this._getUnsafe(x, y);
|
||||||
consumer.accept(t, new Pos2D(x, y));
|
consumer.accept(t, new Pos2D(x, y));
|
||||||
@@ -412,7 +412,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
Pos2D min = this.minPosRef.get();
|
Pos2D min = this.minPosRef.get();
|
||||||
for (Pos2D offset : this.ringPositionIteratorArray)
|
for (Pos2D offset : this.ringPositionIteratorArray)
|
||||||
{
|
{
|
||||||
T item = this._getUnsafe(min.x + offset.x, min.y + offset.y);
|
T item = this._getUnsafe(min.getX() + offset.getX(), min.getY() + offset.getY());
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
consumer.accept(item);
|
consumer.accept(item);
|
||||||
@@ -443,9 +443,9 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
Pos2D min = this.minPosRef.get();
|
Pos2D min = this.minPosRef.get();
|
||||||
for (Pos2D offset : this.ringPositionIteratorArray)
|
for (Pos2D offset : this.ringPositionIteratorArray)
|
||||||
{
|
{
|
||||||
LodUtil.assertTrue(this._inRangeAcquired(min.x + offset.x, min.y + offset.y, min));
|
LodUtil.assertTrue(this._inRangeAcquired(min.getX() + offset.getX(), min.getY() + offset.getY(), min));
|
||||||
T item = this._getUnsafe(min.x + offset.x, min.y + offset.y);
|
T item = this._getUnsafe(min.getX() + offset.getX(), min.getY() + offset.getY());
|
||||||
consumer.accept(item, new Pos2D(min.x + offset.x, min.y + offset.y));
|
consumer.accept(item, new Pos2D(min.getX() + offset.getX(), min.getY() + offset.getY()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -479,8 +479,8 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
// sort the positions from nearest to farthest from the world origin
|
// sort the positions from nearest to farthest from the world origin
|
||||||
Arrays.sort(posArray, (a, b) ->
|
Arrays.sort(posArray, (a, b) ->
|
||||||
{
|
{
|
||||||
long disSqrA = (long) a.x * a.x + (long) a.y * a.y;
|
long disSqrA = (long) a.getX() * a.getX() + (long) a.getY() * a.getY();
|
||||||
long disSqrB = (long) b.x * b.x + (long) b.y * b.y;
|
long disSqrB = (long) b.getX() * b.getX() + (long) b.getY() * b.getY();
|
||||||
return Double.compare(disSqrA, disSqrB);
|
return Double.compare(disSqrA, disSqrB);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -490,8 +490,8 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
}
|
}
|
||||||
for (Pos2D pos2D : posArray)
|
for (Pos2D pos2D : posArray)
|
||||||
{
|
{
|
||||||
LodUtil.assertTrue(pos2D.x >= 0 && pos2D.x < this.width);
|
LodUtil.assertTrue(pos2D.getX() >= 0 && pos2D.getX() < this.width);
|
||||||
LodUtil.assertTrue(pos2D.y >= 0 && pos2D.y < this.width);
|
LodUtil.assertTrue(pos2D.getY() >= 0 && pos2D.getY() < this.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ringPositionIteratorArray = posArray;
|
this.ringPositionIteratorArray = posArray;
|
||||||
@@ -508,7 +508,7 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T>
|
|||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
Pos2D p = this.minPosRef.get();
|
Pos2D p = this.minPosRef.get();
|
||||||
return this.getClass().getSimpleName() + "[" + (p.x + this.halfWidth) + "," + (p.y + this.halfWidth) + "] " + this.width + "*" + this.width + "[" + this.size() + "]";
|
return this.getClass().getSimpleName() + "[" + (p.getX() + this.halfWidth) + "," + (p.getY() + this.halfWidth) + "] " + this.width + "*" + this.width + "[" + this.size() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toDetailString()
|
public String toDetailString()
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.core.util.math;
|
package com.seibel.distanthorizons.core.util.math;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||||
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,7 +135,6 @@ public class Vec3d extends DhApiVec3d
|
|||||||
|
|
||||||
public Vec3d copy() { return new Vec3d(this.x, this.y, this.z); }
|
public Vec3d copy() { return new Vec3d(this.x, this.y, this.z); }
|
||||||
|
|
||||||
// Forge start
|
|
||||||
public Vec3d(double[] values) { this.set(values); }
|
public Vec3d(double[] values) { this.set(values); }
|
||||||
|
|
||||||
public void set(double[] values)
|
public void set(double[] values)
|
||||||
@@ -144,4 +144,31 @@ public class Vec3d extends DhApiVec3d
|
|||||||
this.z = values[2];
|
this.z = values[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double getManhattanDistance(DhApiVec3d a, DhApiVec3d b)
|
||||||
|
{
|
||||||
|
return Math.abs(a.x - b.x)
|
||||||
|
+ Math.abs(a.y - b.y)
|
||||||
|
+ Math.abs(a.z - b.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDistance(DhApiVec3d a, DhApiVec3d b)
|
||||||
|
{
|
||||||
|
return Math.sqrt(Math.pow(a.x - b.x, 2)
|
||||||
|
+ Math.pow(a.y - b.y, 2)
|
||||||
|
+ Math.pow(a.z - b.z, 2));
|
||||||
|
}
|
||||||
|
/** slightly faster version of {@link Vec3d#getDistance} */
|
||||||
|
public static double getSquaredDistance(DhApiVec3d a, DhApiVec3d b)
|
||||||
|
{
|
||||||
|
return Math.pow(a.x - b.x, 2)
|
||||||
|
+ Math.pow(a.y - b.y, 2)
|
||||||
|
+ Math.pow(a.z - b.z, 2);
|
||||||
|
}
|
||||||
|
/** Gets the distance between points A and B, ignoring Y height. */
|
||||||
|
public static double getHorizontalDistance(DhApiVec3d a, DhApiVec3d b)
|
||||||
|
{
|
||||||
|
return Math.sqrt(Math.pow(a.x - b.x, 2)
|
||||||
|
+ Math.pow(a.z - b.z, 2));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
package com.seibel.distanthorizons.core.util.math;
|
package com.seibel.distanthorizons.core.util.math;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
|
||||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package com.seibel.distanthorizons.core.util.objects;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This can be used for easily profiling methods to get the average execution time. <br>
|
||||||
|
* This is a thread safe implementation.
|
||||||
|
*/
|
||||||
|
public class RollingAverage
|
||||||
|
{
|
||||||
|
// properties //
|
||||||
|
|
||||||
|
private final double[] values;
|
||||||
|
private final int size;
|
||||||
|
private int index = 0;
|
||||||
|
private double sum = 0.0;
|
||||||
|
private final Lock arrayLock = new ReentrantLock();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public RollingAverage(int size)
|
||||||
|
{
|
||||||
|
if (size <= 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Size must be greater than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.size = size;
|
||||||
|
this.values = new double[size];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======//
|
||||||
|
// input //
|
||||||
|
//=======//
|
||||||
|
|
||||||
|
public void addValue(double value)
|
||||||
|
{
|
||||||
|
this.arrayLock.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Subtract the oldest value from the sum
|
||||||
|
this.sum -= this.values[this.index];
|
||||||
|
// Update the buffer with the new value
|
||||||
|
this.values[this.index] = value;
|
||||||
|
// Add the new value to the sum
|
||||||
|
this.sum += value;
|
||||||
|
// Move to the next index
|
||||||
|
this.index = (this.index + 1) % this.size;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.arrayLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear()
|
||||||
|
{
|
||||||
|
this.arrayLock.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.sum = 0;
|
||||||
|
this.index = 0;
|
||||||
|
Arrays.fill(this.values, 0);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.arrayLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// output //
|
||||||
|
//========//
|
||||||
|
|
||||||
|
/** Gets the current rolling average. */
|
||||||
|
public double getAverage()
|
||||||
|
{
|
||||||
|
this.arrayLock.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (this.sum / this.size);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
this.arrayLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** rounded to two decimals*/
|
||||||
|
public String getAverageRoundedString() { return String.format("%.2f", this.getAverage()); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() { return "avg: "+this.getAverageRoundedString()+" max count: "+this.size; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+1
-1
@@ -350,6 +350,6 @@ public class QuadNode<T>
|
|||||||
//==============//
|
//==============//
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() { return "pos: " + this.sectionPos + ", children #: " + this.getTotalChildCount() + ", value: " + this.value; }
|
public String toString() { return "pos: " + DhSectionPos.toString(this.sectionPos) + ", children #: " + this.getTotalChildCount() + ", value: " + this.value; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-4
@@ -20,7 +20,7 @@
|
|||||||
package com.seibel.distanthorizons.core.util.objects.quadTree;
|
package com.seibel.distanthorizons.core.util.objects.quadTree;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.pos.Pos2D;
|
import com.seibel.distanthorizons.core.pos.Pos2D;
|
||||||
@@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.util.gridList.MovableGridRingList;
|
|||||||
import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue;
|
import it.unimi.dsi.fastutil.longs.LongArrayFIFOQueue;
|
||||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -85,7 +86,7 @@ public class QuadTree<T>
|
|||||||
Pos2D ringListCenterPos = new Pos2D(
|
Pos2D ringListCenterPos = new Pos2D(
|
||||||
BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.x, this.treeMinDetailLevel),
|
BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.x, this.treeMinDetailLevel),
|
||||||
BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.z, this.treeMinDetailLevel));
|
BitShiftUtil.divideByPowerOfTwo(this.centerBlockPos.z, this.treeMinDetailLevel));
|
||||||
this.topRingList = new MovableGridRingList<>(halfSizeInRootNodes, ringListCenterPos.x, ringListCenterPos.y);
|
this.topRingList = new MovableGridRingList<>(halfSizeInRootNodes, ringListCenterPos.getX(), ringListCenterPos.getY());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +97,10 @@ public class QuadTree<T>
|
|||||||
//=====================//
|
//=====================//
|
||||||
|
|
||||||
/** @return the node at the given section position */
|
/** @return the node at the given section position */
|
||||||
|
@Nullable
|
||||||
public final QuadNode<T> getNode(long pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, true); }
|
public final QuadNode<T> getNode(long pos) throws IndexOutOfBoundsException { return this.getOrSetNode(pos, false, null, true); }
|
||||||
/** @return the value at the given section position */
|
/** @return the value at the given section position */
|
||||||
|
@Nullable
|
||||||
public final T getValue(long pos) throws IndexOutOfBoundsException
|
public final T getValue(long pos) throws IndexOutOfBoundsException
|
||||||
{
|
{
|
||||||
QuadNode<T> node = this.getNode(pos);
|
QuadNode<T> node = this.getNode(pos);
|
||||||
@@ -109,6 +112,7 @@ public class QuadTree<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return the value that was previously in the given position, null if nothing */
|
/** @return the value that was previously in the given position, null if nothing */
|
||||||
|
@Nullable
|
||||||
public final T setValue(long pos, T value) throws IndexOutOfBoundsException
|
public final T setValue(long pos, T value) throws IndexOutOfBoundsException
|
||||||
{
|
{
|
||||||
T previousValue = this.getValue(pos);
|
T previousValue = this.getValue(pos);
|
||||||
@@ -117,6 +121,7 @@ public class QuadTree<T>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @param runBoundaryChecks should only ever be set to true internally for removing out of bound nodes */
|
/** @param runBoundaryChecks should only ever be set to true internally for removing out of bound nodes */
|
||||||
|
@Nullable
|
||||||
protected final QuadNode<T> getOrSetNode(long pos, boolean setNewValue, T newValue, boolean runBoundaryChecks) throws IndexOutOfBoundsException
|
protected final QuadNode<T> getOrSetNode(long pos, boolean setNewValue, T newValue, boolean runBoundaryChecks) throws IndexOutOfBoundsException
|
||||||
{
|
{
|
||||||
if (runBoundaryChecks && !this.isSectionPosInBounds(pos))
|
if (runBoundaryChecks && !this.isSectionPosInBounds(pos))
|
||||||
@@ -260,7 +265,7 @@ public class QuadTree<T>
|
|||||||
|
|
||||||
|
|
||||||
// remove out of bounds root nodes
|
// remove out of bounds root nodes
|
||||||
this.topRingList.moveTo(expectedCenterPos.x, expectedCenterPos.y, (quadNode) ->
|
this.topRingList.moveTo(expectedCenterPos.getX(), expectedCenterPos.getY(), (quadNode) ->
|
||||||
{
|
{
|
||||||
if (quadNode != null && removedItemConsumer != null)
|
if (quadNode != null && removedItemConsumer != null)
|
||||||
{
|
{
|
||||||
@@ -409,7 +414,7 @@ public class QuadTree<T>
|
|||||||
{
|
{
|
||||||
if (node != null || includeNullNodes)
|
if (node != null || includeNullNodes)
|
||||||
{
|
{
|
||||||
long rootPos = DhSectionPos.encode(QuadTree.this.treeMinDetailLevel, pos2D.x, pos2D.y);
|
long rootPos = DhSectionPos.encode(QuadTree.this.treeMinDetailLevel, pos2D.getX(), pos2D.getY());
|
||||||
if (QuadTree.this.isSectionPosInBounds(rootPos))
|
if (QuadTree.this.isSectionPosInBounds(rootPos))
|
||||||
{
|
{
|
||||||
this.iteratorPosQueue.enqueue(rootPos);
|
this.iteratorPosQueue.enqueue(rootPos);
|
||||||
|
|||||||
+7
-7
@@ -66,6 +66,11 @@ public class ThreadPoolUtil
|
|||||||
@Nullable
|
@Nullable
|
||||||
public static ThreadPoolExecutor getCleanupExecutor() { return cleanupThreadPool; }
|
public static ThreadPoolExecutor getCleanupExecutor() { return cleanupThreadPool; }
|
||||||
|
|
||||||
|
public static final String BEACON_CULLING_THREAD_NAME = "Beacon Culling";
|
||||||
|
private static ThreadPoolExecutor beaconCullingThreadPool;
|
||||||
|
@Nullable
|
||||||
|
public static ThreadPoolExecutor getBeaconCullingExecutor() { return beaconCullingThreadPool; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//======================//
|
//======================//
|
||||||
@@ -76,11 +81,6 @@ public class ThreadPoolUtil
|
|||||||
// and all share an underlying number of threads.
|
// and all share an underlying number of threads.
|
||||||
// WARNING: great care should be used when setting up these threads since deadlock can occur if they are handled poorly.
|
// WARNING: great care should be used when setting up these threads since deadlock can occur if they are handled poorly.
|
||||||
|
|
||||||
public static final DhThreadFactory LIGHT_POPULATOR_THREAD_FACTORY = new DhThreadFactory("LOD Builder - Light Populator", Thread.MIN_PRIORITY);
|
|
||||||
private static ConfigThreadPool lightPopulatorThreadPool;
|
|
||||||
@Nullable
|
|
||||||
public static ThreadPoolExecutor getLightPopulatorExecutor() { return (lightPopulatorThreadPool != null) ? lightPopulatorThreadPool.executor : null; }
|
|
||||||
|
|
||||||
public static final DhThreadFactory CHUNK_TO_LOD_BUILDER_THREAD_FACTORY = new DhThreadFactory("LOD Builder - Chunk to Lod Builder", Thread.MIN_PRIORITY);
|
public static final DhThreadFactory CHUNK_TO_LOD_BUILDER_THREAD_FACTORY = new DhThreadFactory("LOD Builder - Chunk to Lod Builder", Thread.MIN_PRIORITY);
|
||||||
private static ConfigThreadPool chunkToLodBuilderThreadPool;
|
private static ConfigThreadPool chunkToLodBuilderThreadPool;
|
||||||
@Nullable
|
@Nullable
|
||||||
@@ -114,6 +114,7 @@ public class ThreadPoolUtil
|
|||||||
worldGenThreadPool = new ConfigThreadPool(WORLD_GEN_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads, null);
|
worldGenThreadPool = new ConfigThreadPool(WORLD_GEN_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads, null);
|
||||||
bufferUploaderThreadPool = ThreadUtil.makeSingleThreadPool(BUFFER_UPLOADER_THREAD_NAME);
|
bufferUploaderThreadPool = ThreadUtil.makeSingleThreadPool(BUFFER_UPLOADER_THREAD_NAME);
|
||||||
cleanupThreadPool = ThreadUtil.makeSingleThreadPool(CLEANUP_THREAD_NAME);
|
cleanupThreadPool = ThreadUtil.makeSingleThreadPool(CLEANUP_THREAD_NAME);
|
||||||
|
beaconCullingThreadPool = ThreadUtil.makeSingleThreadPool(BEACON_CULLING_THREAD_NAME);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -141,7 +142,6 @@ public class ThreadPoolUtil
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create thread pools
|
// create thread pools
|
||||||
lightPopulatorThreadPool = new ConfigThreadPool(LIGHT_POPULATOR_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForLodBuilderThreads, workerThreadSemaphore);
|
|
||||||
chunkToLodBuilderThreadPool = new ConfigThreadPool(CHUNK_TO_LOD_BUILDER_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForLodBuilderThreads, workerThreadSemaphore);
|
chunkToLodBuilderThreadPool = new ConfigThreadPool(CHUNK_TO_LOD_BUILDER_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForLodBuilderThreads, workerThreadSemaphore);
|
||||||
bufferBuilderThreadPool = new ConfigThreadPool(BUFFER_BUILDER_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForLodBuilderThreads, workerThreadSemaphore);
|
bufferBuilderThreadPool = new ConfigThreadPool(BUFFER_BUILDER_THREAD_FACTORY, Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads, Config.Client.Advanced.MultiThreading.runTimeRatioForLodBuilderThreads, workerThreadSemaphore);
|
||||||
|
|
||||||
@@ -155,10 +155,10 @@ public class ThreadPoolUtil
|
|||||||
worldGenThreadPool.shutdownExecutorService();
|
worldGenThreadPool.shutdownExecutorService();
|
||||||
bufferUploaderThreadPool.shutdown();
|
bufferUploaderThreadPool.shutdown();
|
||||||
cleanupThreadPool.shutdown();
|
cleanupThreadPool.shutdown();
|
||||||
|
beaconCullingThreadPool.shutdown();
|
||||||
|
|
||||||
|
|
||||||
// worker threads
|
// worker threads
|
||||||
ThreadPoolUtil.lightPopulatorThreadPool.shutdownExecutorService();
|
|
||||||
ThreadPoolUtil.chunkToLodBuilderThreadPool.shutdownExecutorService();
|
ThreadPoolUtil.chunkToLodBuilderThreadPool.shutdownExecutorService();
|
||||||
ThreadPoolUtil.bufferBuilderThreadPool.shutdownExecutorService();
|
ThreadPoolUtil.bufferBuilderThreadPool.shutdownExecutorService();
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -47,9 +47,15 @@ public interface IBlockStateWrapper extends IDhApiBlockStateWrapper
|
|||||||
byte getMaterialId();
|
byte getMaterialId();
|
||||||
|
|
||||||
boolean isBeaconBlock();
|
boolean isBeaconBlock();
|
||||||
|
/** IE a glass block that can affect the beacon beam color */
|
||||||
|
boolean isBeaconTintBlock();
|
||||||
|
/**
|
||||||
|
* The blocks used by a beacon's base
|
||||||
|
* IE Iron, diamond, gold, etc.
|
||||||
|
*/
|
||||||
boolean isBeaconBaseBlock();
|
boolean isBeaconBaseBlock();
|
||||||
|
|
||||||
Color getMapColor();
|
Color getMapColor();
|
||||||
boolean isGlassBlock();
|
Color getBeaconTintColor();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+52
-31
@@ -20,11 +20,15 @@
|
|||||||
package com.seibel.distanthorizons.core.wrapperInterfaces.chunk;
|
package com.seibel.distanthorizons.core.wrapperInterfaces.chunk;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.generation.AdjacentChunkHolder;
|
import com.seibel.distanthorizons.core.generation.AdjacentChunkHolder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPosMutable;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||||
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||||
@@ -90,10 +94,11 @@ public interface IChunkWrapper extends IBindable
|
|||||||
int getSkyLight(int relX, int relY, int relZ);
|
int getSkyLight(int relX, int relY, int relZ);
|
||||||
|
|
||||||
|
|
||||||
ArrayList<DhBlockPos> getBlockLightPosList();
|
/** Note: don't modify this array, it will only be generated once and then shared between uses */
|
||||||
|
ArrayList<DhBlockPos> getWorldBlockLightPosList();
|
||||||
|
|
||||||
|
|
||||||
default boolean blockPosInsideChunk(DhBlockPos blockPos) { return this.blockPosInsideChunk(blockPos.x, blockPos.y, blockPos.z); }
|
default boolean blockPosInsideChunk(DhBlockPos blockPos) { return this.blockPosInsideChunk(blockPos.getX(), blockPos.getY(), blockPos.getZ()); }
|
||||||
default boolean blockPosInsideChunk(int x, int y, int z)
|
default boolean blockPosInsideChunk(int x, int y, int z)
|
||||||
{
|
{
|
||||||
return (x >= this.getMinBlockX() && x <= this.getMaxBlockX()
|
return (x >= this.getMinBlockX() && x <= this.getMaxBlockX()
|
||||||
@@ -110,7 +115,7 @@ public interface IChunkWrapper extends IBindable
|
|||||||
String toString();
|
String toString();
|
||||||
|
|
||||||
|
|
||||||
default IBlockStateWrapper getBlockState(DhBlockPos pos) { return this.getBlockState(pos.x, pos.y, pos.z); }
|
default IBlockStateWrapper getBlockState(DhBlockPos pos) { return this.getBlockState(pos.getX(), pos.getY(), pos.getZ()); }
|
||||||
IBlockStateWrapper getBlockState(int relX, int relY, int relZ);
|
IBlockStateWrapper getBlockState(int relX, int relY, int relZ);
|
||||||
|
|
||||||
IBiomeWrapper getBiome(int relX, int relY, int relZ);
|
IBiomeWrapper getBiome(int relX, int relY, int relZ);
|
||||||
@@ -282,8 +287,8 @@ public interface IChunkWrapper extends IBindable
|
|||||||
int primeBiomeMultiplier = 701;
|
int primeBiomeMultiplier = 701;
|
||||||
int primeHeightMultiplier = 137;
|
int primeHeightMultiplier = 137;
|
||||||
|
|
||||||
int minBuildHeight = this.getMaxNonEmptyHeight();
|
int minBuildHeight = this.getMinNonEmptyHeight();
|
||||||
int maxBuildHeight = this.getMinNonEmptyHeight();
|
int maxBuildHeight = this.getMaxNonEmptyHeight();
|
||||||
|
|
||||||
|
|
||||||
// most blocks (only some blocks are sampled since checking every block is a very slow operation)
|
// most blocks (only some blocks are sampled since checking every block is a very slow operation)
|
||||||
@@ -291,7 +296,7 @@ public interface IChunkWrapper extends IBindable
|
|||||||
{
|
{
|
||||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z+=2)
|
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z+=2)
|
||||||
{
|
{
|
||||||
for (int y = minBuildHeight; y < maxBuildHeight; y+=8)
|
for (int y = minBuildHeight; y < maxBuildHeight; y+=2)
|
||||||
{
|
{
|
||||||
hash = (hash * primeBlockMultiplier) + this.getBlockState(x, y, z).hashCode();
|
hash = (hash * primeBlockMultiplier) + this.getBlockState(x, y, z).hashCode();
|
||||||
hash = (hash * primeBiomeMultiplier) + this.getBiome(x, y, z).hashCode();
|
hash = (hash * primeBiomeMultiplier) + this.getBiome(x, y, z).hashCode();
|
||||||
@@ -320,6 +325,19 @@ public interface IChunkWrapper extends IBindable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// light emitting blocks (if the light changes then the LOD definitely needs to be updated)
|
||||||
|
final DhBlockPosMutable relPos = new DhBlockPosMutable();
|
||||||
|
ArrayList<DhBlockPos> lightPosList = this.getWorldBlockLightPosList();
|
||||||
|
for (int i = 0; i < lightPosList.size(); i++)
|
||||||
|
{
|
||||||
|
DhBlockPos pos = lightPosList.get(i);
|
||||||
|
pos.mutateToChunkRelativePos(relPos);
|
||||||
|
|
||||||
|
hash = (hash * primeBlockMultiplier) + this.getBlockState(relPos.getX(), relPos.getY(), relPos.getZ()).hashCode();
|
||||||
|
hash = (hash * primeHeightMultiplier) + relPos.getY();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,20 +347,24 @@ public interface IChunkWrapper extends IBindable
|
|||||||
|
|
||||||
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(this, neighbourChunkList);
|
AdjacentChunkHolder adjacentChunkHolder = new AdjacentChunkHolder(this, neighbourChunkList);
|
||||||
|
|
||||||
// since beacons emit light we can check only the positions that are emitting light
|
// find the beacon block positions,
|
||||||
ArrayList<DhBlockPos> blockPosList = this.getBlockLightPosList();
|
// since beacons emit light we only need to check the positions that emit light
|
||||||
|
final DhBlockPosMutable relPos = new DhBlockPosMutable();
|
||||||
|
ArrayList<DhBlockPos> blockPosList = this.getWorldBlockLightPosList();
|
||||||
for (int i = 0; i < blockPosList.size(); i++)
|
for (int i = 0; i < blockPosList.size(); i++)
|
||||||
{
|
{
|
||||||
DhBlockPos pos = blockPosList.get(i);
|
DhBlockPos pos = blockPosList.get(i);
|
||||||
DhBlockPos relPos = pos.convertToChunkRelativePos();
|
pos.mutateToChunkRelativePos(relPos);
|
||||||
|
|
||||||
|
|
||||||
IBlockStateWrapper block = this.getBlockState(relPos);
|
IBlockStateWrapper block = this.getBlockState(relPos);
|
||||||
if (block.isBeaconBlock())
|
if (block.isBeaconBlock())
|
||||||
{
|
{
|
||||||
|
// check if this beacon is active and if so what color it should be
|
||||||
Color beaconColor = getBeaconColor(pos, adjacentChunkHolder);
|
Color beaconColor = getBeaconColor(pos, adjacentChunkHolder);
|
||||||
if (beaconColor != null)
|
if (beaconColor != null)
|
||||||
{
|
{
|
||||||
|
// beacon is active
|
||||||
BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), beaconColor);
|
BeaconBeamDTO beam = new BeaconBeamDTO(blockPosList.get(i), beaconColor);
|
||||||
beaconBeamList.add(beam);
|
beaconBeamList.add(beam);
|
||||||
}
|
}
|
||||||
@@ -355,8 +377,8 @@ public interface IChunkWrapper extends IBindable
|
|||||||
@Nullable
|
@Nullable
|
||||||
static Color getBeaconColor(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder)
|
static Color getBeaconColor(DhBlockPos beaconPos, AdjacentChunkHolder chunkHolder)
|
||||||
{
|
{
|
||||||
DhBlockPos beaconRelPos = beaconPos.convertToChunkRelativePos();
|
DhBlockPos beaconRelPos = beaconPos.createChunkRelativePos();
|
||||||
DhBlockPos baseRelPos = new DhBlockPos(0, beaconRelPos.y-1, 0);
|
DhBlockPosMutable baseRelPos = new DhBlockPosMutable(0, beaconRelPos.getY() -1, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -368,14 +390,15 @@ public interface IChunkWrapper extends IBindable
|
|||||||
{
|
{
|
||||||
for (int z = -1; z <= 1; z++)
|
for (int z = -1; z <= 1; z++)
|
||||||
{
|
{
|
||||||
baseRelPos.x = beaconRelPos.x + x;
|
baseRelPos.setX(beaconRelPos.getX() + x);
|
||||||
baseRelPos.z = beaconRelPos.z + z;
|
baseRelPos.setZ(beaconRelPos.getZ() + z);
|
||||||
baseRelPos.mutateToChunkRelativePos(baseRelPos);
|
baseRelPos.mutateToChunkRelativePos(baseRelPos);
|
||||||
|
|
||||||
IChunkWrapper chunk = chunkHolder.getByBlockPos(beaconPos.x + x, beaconPos.z + z);
|
// if no chunk is loaded assume the beacon is complete in that direction
|
||||||
|
IChunkWrapper chunk = chunkHolder.getByBlockPos(beaconPos.getX() + x, beaconPos.getZ() + z);
|
||||||
if (chunk != null)
|
if (chunk != null)
|
||||||
{
|
{
|
||||||
IBlockStateWrapper block = chunk.getBlockState(baseRelPos.x, baseRelPos.y, baseRelPos.z);
|
IBlockStateWrapper block = chunk.getBlockState(baseRelPos.getX(), baseRelPos.getY(), baseRelPos.getZ());
|
||||||
if (!block.isBeaconBaseBlock())
|
if (!block.isBeaconBaseBlock())
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -394,37 +417,35 @@ public interface IChunkWrapper extends IBindable
|
|||||||
int red = 0;
|
int red = 0;
|
||||||
int green = 0;
|
int green = 0;
|
||||||
int blue = 0;
|
int blue = 0;
|
||||||
boolean glassBlockFound = false;
|
boolean beaconTintBlockFound = false;
|
||||||
|
|
||||||
IChunkWrapper centerChunk = chunkHolder.getByBlockPos(beaconPos.x, beaconPos.z);
|
IChunkWrapper centerChunk = chunkHolder.getByBlockPos(beaconPos.getX(), beaconPos.getZ());
|
||||||
int maxY = centerChunk.getMaxNonEmptyHeight();
|
int maxY = centerChunk.getMaxNonEmptyHeight();
|
||||||
for (int y = beaconRelPos.y+1; y <= maxY; y++)
|
for (int y = beaconRelPos.getY() +1; y <= maxY; y++)
|
||||||
{
|
{
|
||||||
IBlockStateWrapper block = centerChunk.getBlockState(beaconRelPos.x, y, beaconRelPos.z);
|
IBlockStateWrapper block = centerChunk.getBlockState(beaconRelPos.getX(), y, beaconRelPos.getZ());
|
||||||
if (!block.isAir() && block.getOpacity() == LodUtil.BLOCK_FULLY_OPAQUE)
|
if (!block.isAir() && block.getOpacity() == LodUtil.BLOCK_FULLY_OPAQUE)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (block.isGlassBlock()
|
if (block.isBeaconTintBlock())
|
||||||
// ignore invisible blocks (which have pure black as their map color, luckily black stained-glass is actually extremely dark gray)
|
|
||||||
&& !block.getMapColor().equals(Color.BLACK))
|
|
||||||
{
|
{
|
||||||
red += block.getMapColor().getRed();
|
red += block.getBeaconTintColor().getRed();
|
||||||
green += block.getMapColor().getGreen();
|
green += block.getBeaconTintColor().getGreen();
|
||||||
blue += block.getMapColor().getBlue();
|
blue += block.getBeaconTintColor().getBlue();
|
||||||
|
|
||||||
if (glassBlockFound)
|
if (beaconTintBlockFound)
|
||||||
{
|
{
|
||||||
red /= 2;
|
red /= 2;
|
||||||
green /= 2;
|
green /= 2;
|
||||||
blue /= 2;
|
blue /= 2;
|
||||||
}
|
}
|
||||||
glassBlockFound = true;
|
beaconTintBlockFound = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return glassBlockFound ? new Color(red, green, blue) : Color.WHITE;
|
return beaconTintBlockFound ? new Color(red, green, blue) : Color.WHITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -19,12 +19,11 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.core.wrapperInterfaces.minecraft;
|
package com.seibel.distanthorizons.core.wrapperInterfaces.minecraft;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
|||||||
-9
@@ -20,20 +20,11 @@
|
|||||||
package com.seibel.distanthorizons.core.wrapperInterfaces.minecraft;
|
package com.seibel.distanthorizons.core.wrapperInterfaces.minecraft;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.util.HashSet;
|
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
|
||||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
|
||||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
|
||||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -19,10 +19,12 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.core.wrapperInterfaces.world;
|
package com.seibel.distanthorizons.core.wrapperInterfaces.world;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @version 2022-9-16
|
* @version 2022-9-16
|
||||||
*/
|
*/
|
||||||
@@ -41,4 +43,6 @@ public interface IClientLevelWrapper extends ILevelWrapper
|
|||||||
@Nullable
|
@Nullable
|
||||||
IBiomeWrapper getPlainsBiomeWrapper();
|
IBiomeWrapper getPlainsBiomeWrapper();
|
||||||
|
|
||||||
|
Color getCloudColor(float tickDelta);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -19,10 +19,9 @@
|
|||||||
|
|
||||||
package com.seibel.distanthorizons.core.wrapperInterfaces.world;
|
package com.seibel.distanthorizons.core.wrapperInterfaces.world;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiDimensionTypeWrapper;
|
|
||||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
|||||||
@@ -308,7 +308,11 @@
|
|||||||
"distanthorizons.config.client.advanced.graphics.advancedGraphics.grassSideRendering":
|
"distanthorizons.config.client.advanced.graphics.advancedGraphics.grassSideRendering":
|
||||||
"Grass Side Rendering",
|
"Grass Side Rendering",
|
||||||
"distanthorizons.config.client.advanced.graphics.advancedGraphics.grassSideRendering.@tooltip":
|
"distanthorizons.config.client.advanced.graphics.advancedGraphics.grassSideRendering.@tooltip":
|
||||||
"How should the sides and bottom of grass block LODs render?",
|
"How should the sides and bottom of grass block LODs render?",
|
||||||
|
"distanthorizons.config.client.advanced.graphics.advancedGraphics.disableBeaconDistanceCulling":
|
||||||
|
"Disable Beacon Distance Culling",
|
||||||
|
"distanthorizons.config.client.advanced.graphics.advancedGraphics.disableBeaconDistanceCulling.@tooltip":
|
||||||
|
"If true all beacons near the camera won't be drawn to prevent vanilla overdraw. \nIf false all beacons will be rendered.",
|
||||||
|
|
||||||
|
|
||||||
"distanthorizons.config.client.advanced.graphics.genericRendering":
|
"distanthorizons.config.client.advanced.graphics.genericRendering":
|
||||||
@@ -358,9 +362,12 @@
|
|||||||
|
|
||||||
"distanthorizons.config.client.advanced.lodBuilding.minTimeBetweenChunkUpdatesInSeconds":
|
"distanthorizons.config.client.advanced.lodBuilding.minTimeBetweenChunkUpdatesInSeconds":
|
||||||
"Minimum Time Between Chunk Updates In Seconds",
|
"Minimum Time Between Chunk Updates In Seconds",
|
||||||
|
|
||||||
"distanthorizons.config.client.advanced.lodBuilding.minTimeBetweenChunkUpdatesInSeconds.@tooltip":
|
"distanthorizons.config.client.advanced.lodBuilding.minTimeBetweenChunkUpdatesInSeconds.@tooltip":
|
||||||
"Determines how long must pass between LOD chunk updates before another. \nupdate can occur\n\nIncreasing this value will reduce CPU load but may may cause \nLODs to become outdated more frequently or for longer.",
|
"Determines how long must pass between LOD chunk updates before another. \nupdate can occur\n\nIncreasing this value will reduce CPU load but may may cause \nLODs to become outdated more frequently or for longer.",
|
||||||
|
"distanthorizons.config.client.advanced.lodBuilding.disableUnchangedChunkCheck":
|
||||||
|
"Disable Unchanged Chunk Check",
|
||||||
|
"distanthorizons.config.client.advanced.lodBuilding.disableUnchangedChunkCheck.@tooltip":
|
||||||
|
"Disabling this check may fix issues where LODs aren't updated after\nblocks have been changed.\n",
|
||||||
"distanthorizons.config.client.advanced.lodBuilding.onlyUseDhLightingEngine":
|
"distanthorizons.config.client.advanced.lodBuilding.onlyUseDhLightingEngine":
|
||||||
"Only Use DH Lighting Engine",
|
"Only Use DH Lighting Engine",
|
||||||
"distanthorizons.config.client.advanced.lodBuilding.onlyUseDhLightingEngine.@tooltip":
|
"distanthorizons.config.client.advanced.lodBuilding.onlyUseDhLightingEngine.@tooltip":
|
||||||
|
|||||||
@@ -114,8 +114,8 @@ public class LightingTestBlockStateWrapper implements IBlockStateWrapper
|
|||||||
@Override
|
@Override
|
||||||
public Color getMapColor() { throw new UnsupportedOperationException("Not Implemented"); }
|
public Color getMapColor() { throw new UnsupportedOperationException("Not Implemented"); }
|
||||||
@Override
|
@Override
|
||||||
public boolean isGlassBlock() { throw new UnsupportedOperationException("Not Implemented"); }
|
public boolean isBeaconTintBlock() { throw new UnsupportedOperationException("Not Implemented"); }
|
||||||
|
@Override
|
||||||
|
public Color getBeaconTintColor() { throw new UnsupportedOperationException("Not Implemented"); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
package testItems.lightingEngine;
|
package testItems.lightingEngine;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
|
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
|
||||||
@@ -399,7 +399,7 @@ public class LightingTestChunkWrapper implements IChunkWrapper
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<DhBlockPos> getBlockLightPosList() { return this.blockLightPosList; }
|
public ArrayList<DhBlockPos> getWorldBlockLightPosList() { return this.blockLightPosList; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean doNearbyChunksExist() { return false; }
|
public boolean doNearbyChunksExist() { return false; }
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class TestCompoundKeyRepo extends AbstractDhRepo<DhChunkPos, TestCompound
|
|||||||
@Override
|
@Override
|
||||||
public String getTableName() { return "TestCompound"; }
|
public String getTableName() { return "TestCompound"; }
|
||||||
@Override
|
@Override
|
||||||
public String createWhereStatement(DhChunkPos key) { return "XPos = '"+key.x+"' AND ZPos = '"+key.z+"'"; }
|
public String createWhereStatement(DhChunkPos key) { return "XPos = '"+key.getX()+"' AND ZPos = '"+key.getZ()+"'"; }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -75,8 +75,8 @@ public class TestCompoundKeyRepo extends AbstractDhRepo<DhChunkPos, TestCompound
|
|||||||
PreparedStatement statement = this.createPreparedStatement(sql);
|
PreparedStatement statement = this.createPreparedStatement(sql);
|
||||||
|
|
||||||
int i = 1; // post-increment for the win!
|
int i = 1; // post-increment for the win!
|
||||||
statement.setObject(i++, dto.id.x);
|
statement.setObject(i++, dto.id.getX());
|
||||||
statement.setObject(i++, dto.id.z);
|
statement.setObject(i++, dto.id.getZ());
|
||||||
|
|
||||||
statement.setObject(i++, dto.value);
|
statement.setObject(i++, dto.value);
|
||||||
|
|
||||||
@@ -96,8 +96,8 @@ public class TestCompoundKeyRepo extends AbstractDhRepo<DhChunkPos, TestCompound
|
|||||||
int i = 1;
|
int i = 1;
|
||||||
statement.setObject(i++, dto.value);
|
statement.setObject(i++, dto.value);
|
||||||
|
|
||||||
statement.setObject(i++, dto.id.x);
|
statement.setObject(i++, dto.id.getX());
|
||||||
statement.setObject(i++, dto.id.z);
|
statement.setObject(i++, dto.id.getZ());
|
||||||
|
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ package tests;
|
|||||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
package tests;
|
package tests;
|
||||||
|
|
||||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
|||||||
Reference in New Issue
Block a user