diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index ef7851f9d..cb45e4ac4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -1362,6 +1362,37 @@ public class Config + "") .build(); + public static ConfigEntry generationCenterChunkX = new ConfigEntry.Builder() + .setChatCommandName("generation.bounds.centerChunk.x") + .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) + .setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE) + .comment("" + + "The center X chunk position that the world gen max radius is centered around. \n" + + "") + .build(); + public static ConfigEntry generationCenterChunkZ = new ConfigEntry.Builder() + .setChatCommandName("generation.bounds.centerChunk.z") + .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) + .setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE) + .comment("" + + "The center Z chunk position that the world gen max radius is centered around. \n" + + "") + .build(); + public static ConfigEntry generationMaxChunkRadius = new ConfigEntry.Builder() + .setChatCommandName("generation.bounds.radiusInChunks") + .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) + .setMinDefaultMax(0, 0, Integer.MAX_VALUE) + .comment("" + + "The max radius in chunks around the central point where world generation is allowed. \n" + + "If this value is set to 0, generation bounds are disabled and the render distance will be used. \n" + + "\n" + + "This should only be set if you have a pre-generated world that has a very limited size. \n" + + "Setting this on a normal MC world will prevent the world generator from filling \n" + + "out your render distance. \n" + + "") + .build(); + + } public static class LodBuilding @@ -1686,32 +1717,6 @@ public class Config "") .build(); - public static ConfigEntry generationBoundsX = new ConfigEntry.Builder() - .setChatCommandName("generation.bounds.x") - .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) - .setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE) - .comment("" + - "Defines the X-coordinate of the central point for generation boundaries, in blocks. \n" + - "") - .build(); - public static ConfigEntry generationBoundsZ = new ConfigEntry.Builder() - .setChatCommandName("generation.bounds.z") - .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) - .setMinDefaultMax(Integer.MIN_VALUE, 0, Integer.MAX_VALUE) - .comment("" + - "Defines the Z-coordinate of the central point for generation boundaries, in blocks. \n" + - "") - .build(); - public static ConfigEntry generationBoundsRadius = new ConfigEntry.Builder() - .setChatCommandName("generation.bounds.radius") - .setAppearance(EConfigEntryAppearance.ONLY_IN_FILE) - .setMinDefaultMax(0, 0, Integer.MAX_VALUE) - .comment("" + - "Defines the radius around the central point within which generation is allowed, in blocks. \n" + - "If this value is set to 0, generation bounds are disabled." + - "") - .build(); - // Real-time updates public static ConfigEntry enableRealTimeUpdates = new ConfigEntry.Builder() diff --git a/core/src/main/java/com/seibel/distanthorizons/core/enums/EMinecraftColor.java b/core/src/main/java/com/seibel/distanthorizons/core/enums/EMinecraftColor.java new file mode 100644 index 000000000..3e4164192 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/enums/EMinecraftColor.java @@ -0,0 +1,12 @@ +package com.seibel.distanthorizons.core.enums; + +/** + * TODO + * might be deprecated in the future? in that case we'll probably want a wrapper + * function to handle colors for new MC versions + * + * source: https://minecraft.wiki/w/Formatting_codes + */ +public class EMinecraftColor +{ +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/RemoteWorldRetrievalQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/RemoteWorldRetrievalQueue.java index 36c4fd7c0..1034b618b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/generation/RemoteWorldRetrievalQueue.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/RemoteWorldRetrievalQueue.java @@ -11,6 +11,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D; import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.util.WorldGenUtil; import com.seibel.distanthorizons.core.util.objects.RollingAverage; import com.seibel.distanthorizons.core.logging.DhLogger; @@ -110,12 +111,14 @@ public class RemoteWorldRetrievalQueue extends AbstractFullDataNetworkRequestQue @Override protected boolean isSectionAllowedToGenerate(long sectionPos, DhBlockPos2D targetPos) { - if (this.networkState.sessionConfig.getGenerationBoundsRadius() > 0) + if (this.networkState.sessionConfig.getGenerationMaxChunkRadius() > 0) { - if (DhSectionPos.getChebyshevSignedBlockDistance(sectionPos, new DhBlockPos2D( - this.networkState.sessionConfig.getGenerationBoundsX(), - this.networkState.sessionConfig.getGenerationBoundsZ() - )) > this.networkState.sessionConfig.getGenerationBoundsRadius()) + boolean posInRange = WorldGenUtil.isPosInWorldGenRange( + sectionPos, + this.networkState.sessionConfig.getGenerationCenterChunkX(), this.networkState.sessionConfig.getGenerationCenterChunkZ(), + this.networkState.sessionConfig.getGenerationMaxChunkRadius() + ); + if (!posInRange) { return false; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java index e30a2e985..9f0ea5c1c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhServerLevel.java @@ -21,6 +21,7 @@ import com.seibel.distanthorizons.core.network.messages.requests.CancelMessage; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D; import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.util.WorldGenUtil; import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; @@ -147,16 +148,15 @@ public abstract class AbstractDhServerLevel extends AbstractDhLevel implements I return; } - if (Config.Server.generationBoundsRadius.get() > 0) + boolean posInRange = WorldGenUtil.isPosInWorldGenRange( + message.sectionPos, + Config.Common.WorldGenerator.generationCenterChunkX.get(), Config.Common.WorldGenerator.generationCenterChunkZ.get(), + Config.Common.WorldGenerator.generationMaxChunkRadius.get() + ); + if (!posInRange) { - if (DhSectionPos.getChebyshevSignedBlockDistance(message.sectionPos, new DhBlockPos2D( - serverPlayerState.sessionConfig.getGenerationBoundsX(), - serverPlayerState.sessionConfig.getGenerationBoundsZ() - )) > Config.Server.generationBoundsRadius.get()) - { - message.sendResponse(new RequestOutOfRangeException("Section out of allowed bounds")); - return; - } + message.sendResponse(new RequestOutOfRangeException("Section out of allowed bounds")); + return; } if (!Config.Server.Experimental.enableNSizedGeneration.get() && DhSectionPos.getDetailLevel(message.sectionPos) != DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java index f73f0e7e4..e1cd8e335 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/config/SessionConfig.java @@ -33,9 +33,9 @@ public class SessionConfig implements INetworkObject registerConfigEntry(Config.Common.WorldGenerator.enableDistantGeneration, Boolean::logicalAnd); registerConfigEntry(Config.Server.maxGenerationRequestDistance, Math::min); - registerConfigEntry(Config.Server.generationBoundsX, (x, y) -> y); - registerConfigEntry(Config.Server.generationBoundsZ, (x, y) -> y); - registerConfigEntry(Config.Server.generationBoundsRadius, (x, y) -> y); + registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkX, (x, y) -> y); + registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkZ, (x, y) -> y); + registerConfigEntry(Config.Common.WorldGenerator.generationMaxChunkRadius, (x, y) -> y); registerConfigEntry(Config.Server.generationRequestRateLimit, Math::min); registerConfigEntry(Config.Server.enableRealTimeUpdates, Boolean::logicalAnd); @@ -68,9 +68,9 @@ public class SessionConfig implements INetworkObject public boolean isDistantGenerationEnabled() { return this.getValue(Config.Common.WorldGenerator.enableDistantGeneration); } public int getMaxGenerationRequestDistance() { return this.getValue(Config.Server.maxGenerationRequestDistance); } - public Integer getGenerationBoundsX() { return this.getValue(Config.Server.generationBoundsX); } - public Integer getGenerationBoundsZ() { return this.getValue(Config.Server.generationBoundsZ); } - public Integer getGenerationBoundsRadius() { return this.getValue(Config.Server.generationBoundsRadius); } + public Integer getGenerationCenterChunkX() { return this.getValue(Config.Common.WorldGenerator.generationCenterChunkX); } + public Integer getGenerationCenterChunkZ() { return this.getValue(Config.Common.WorldGenerator.generationCenterChunkZ); } + public Integer getGenerationMaxChunkRadius() { return this.getValue(Config.Common.WorldGenerator.generationMaxChunkRadius); } public int getGenerationRequestRateLimit() { return this.getValue(Config.Server.generationRequestRateLimit); } public boolean isRealTimeUpdatesEnabled() { return this.getValue(Config.Server.enableRealTimeUpdates); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/server/ServerPlayerState.java b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/server/ServerPlayerState.java index 2de63ef48..b5b86050a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/server/ServerPlayerState.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/multiplayer/server/ServerPlayerState.java @@ -102,8 +102,8 @@ public class ServerPlayerState implements Closeable private void sendConfigMessage() { double coordinateScale = this.getServerPlayer().getLevel().getDimensionType().getCoordinateScale(); - this.sessionConfig.constrainValue(Config.Server.generationBoundsX, (int) (Config.Server.generationBoundsX.get() / coordinateScale)); - this.sessionConfig.constrainValue(Config.Server.generationBoundsZ, (int) (Config.Server.generationBoundsZ.get() / coordinateScale)); + this.sessionConfig.constrainValue(Config.Common.WorldGenerator.generationCenterChunkX, (int) (Config.Common.WorldGenerator.generationCenterChunkX.get() / coordinateScale)); + this.sessionConfig.constrainValue(Config.Common.WorldGenerator.generationCenterChunkZ, (int) (Config.Common.WorldGenerator.generationCenterChunkZ.get() / coordinateScale)); this.networkSession.sendMessage(new SessionConfigMessage(this.sessionConfig)); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java index 31153e7c1..c8c35f223 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/pos/DhSectionPos.java @@ -281,17 +281,22 @@ public class DhSectionPos + Math.abs(getCenterBlockPosZ(pos) - blockPos.z); } + + public static int getChebyshevSignedBlockDistance(long pos, DhBlockPos2D blockPos) + { + return getChebyshevSignedBlockDistance(pos, blockPos); + } /** * Returns the signed distance from a given block to a given section.
* Essentially acts like a distance from the block to the nearest edge of the section, * except inside the section it's negative.
* Useful for detail level insensitive distance comparisons. */ - public static int getChebyshevSignedBlockDistance(long pos, DhBlockPos2D blockPos) + public static int getChebyshevSignedBlockDistance(long pos, DhBlockPos blockPos) { return Math.max( - Math.abs(getCenterBlockPosX(pos) - blockPos.x), - Math.abs(getCenterBlockPosZ(pos) - blockPos.z) + Math.abs(getCenterBlockPosX(pos) - blockPos.getX()), + Math.abs(getCenterBlockPosZ(pos) - blockPos.getZ()) ) - getBlockWidth(pos) / 2; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java index 80d3b1a95..fbd01d09e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodQuadTree.java @@ -762,7 +762,6 @@ public class LodQuadTree extends QuadTree implements IDebugRen { // walk through each node Iterator> nodeIterator = this.nodeIterator(); - ArrayList> renderDataBuildFutures = new ArrayList<>(); while (nodeIterator.hasNext()) { QuadNode quadNode = nodeIterator.next(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index 527b7b9ec..eb5f61814 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -42,7 +42,7 @@ import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; -import com.seibel.distanthorizons.core.util.PerfRecorder; +import com.seibel.distanthorizons.core.util.WorldGenUtil; import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; @@ -528,6 +528,18 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable } long pos = missingGenerationPos.removeLong(i); + + boolean posInRange = WorldGenUtil.isPosInWorldGenRange( + pos, + Config.Common.WorldGenerator.generationCenterChunkX.get(), Config.Common.WorldGenerator.generationCenterChunkZ.get(), + Config.Common.WorldGenerator.generationMaxChunkRadius.get() + ); + if (!posInRange) + { + continue; + } + + boolean positionQueued = (this.fullDataSourceProvider.queuePositionForRetrieval(pos) != null); if (!positionQueued) { diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/WorldGenUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/WorldGenUtil.java new file mode 100644 index 000000000..7c56c8e4e --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/WorldGenUtil.java @@ -0,0 +1,32 @@ +package com.seibel.distanthorizons.core.util; + +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.pos.DhChunkPos; +import com.seibel.distanthorizons.core.pos.DhSectionPos; +import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; + +public class WorldGenUtil +{ + + /** will always return true if a generation max radius isn't set */ + public static boolean isPosInWorldGenRange( + long requestedPos, + int centerChunkX, int centerChunkZ, + int maxChunkRadius) + { + if (Config.Common.WorldGenerator.generationMaxChunkRadius.get() <= 0) + { + return true; + } + + + DhBlockPos centerBlockPos = new DhChunkPos(centerChunkX, centerChunkZ).centerBlockPos(); + int blockDistanceFromCenter = DhSectionPos.getChebyshevSignedBlockDistance(requestedPos, centerBlockPos); + int maxBlockRadius = maxChunkRadius * LodUtil.CHUNK_WIDTH; + boolean requestInRadius = (blockDistanceFromCenter <= maxBlockRadius); + return requestInRadius; + } + + + +}