diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java index 4a0379701..f8584c925 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ServerApi.java @@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.api.internal; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiLevelLoadEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiLevelUnloadEvent; +import com.seibel.distanthorizons.core.generation.DhLightingEngine; import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import com.seibel.distanthorizons.core.level.IDhLevel; @@ -34,6 +35,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import org.apache.logging.log4j.Logger; +import java.util.LinkedList; +import java.util.List; + /** * This holds the methods that should be called by the host mod loader (Fabric, * Forge, etc.). Specifically server events. @@ -153,6 +157,32 @@ public class ServerApi IDhLevel dhLevel = SharedApi.getAbstractDhWorld().getLevel(level); if (dhLevel != null) { + + // Save or populate the chunk wrapper's lighting + // this is done so we don't have to worry about MC unloading the lighting data for this chunk + if (chunk.isLightCorrect()) + { + try + { + chunk.bakeDhLightingUsingMcLightingEngine(); + chunk.setUseDhLighting(true); + } + catch (IllegalStateException e) + { + LOGGER.warn(e.getMessage(), e); + } + } + else + { + // generate the chunk's lighting, ignoring neighbors. + // not a perfect solution, but should prevent chunks from having completely broken lighting + List nearbyChunkList = new LinkedList<>(); + nearbyChunkList.add(chunk); + DhLightingEngine.INSTANCE.lightChunks(chunk, nearbyChunkList, level.hasSkyLight() ? 15 : 0); + chunk.setUseDhLighting(true); + } + + dhLevel.updateChunkAsync(chunk); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java index f699a174f..c48299c66 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/chunk/IChunkWrapper.java @@ -53,6 +53,7 @@ public interface IChunkWrapper extends IBindable long getLongChunkPos(); void setIsDhLightCorrect(boolean isDhLightCorrect); + void setUseDhLighting(boolean useDhLighting); boolean isLightCorrect(); @@ -65,6 +66,34 @@ public interface IChunkWrapper extends IBindable int getBlockLight(int relX, int relY, int relZ); int getSkyLight(int relX, int relY, int relZ); + /** + * Populates DH's saved lighting using MC's lighting engine. + * This is generally done in cases where MC's lighting is correct now, but may not be later (like when a chunk is unloading). + * + * @throws IllegalStateException if the chunk's lighting isn't valid. This is done to prevent accidentally baking broken lighting. + */ + default void bakeDhLightingUsingMcLightingEngine() throws IllegalStateException + { + if (!this.isLightCorrect()) + { + throw new IllegalStateException("Unable to bake lighting for for chunk ["+this.getChunkPos()+"], Minecraft lighting not valid."); + } + + // get the lighting for every relative block pos + for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++) + { + for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++) + { + for (int y = this.getMinBuildHeight(); y < this.getMaxBuildHeight(); y++) + { + this.setDhSkyLight(relX, y, relZ, this.getSkyLight(relX, y, relZ)); + this.setDhBlockLight(relX, y, relZ, this.getBlockLight(relX, y, relZ)); + } + } + } + } + + List getBlockLightPosList();