diff --git a/src/main/java/com/seibel/lod/core/api/ClientApi.java b/src/main/java/com/seibel/lod/core/api/ClientApi.java index eb338e824..7936ff45b 100644 --- a/src/main/java/com/seibel/lod/core/api/ClientApi.java +++ b/src/main/java/com/seibel/lod/core/api/ClientApi.java @@ -19,20 +19,28 @@ package com.seibel.lod.core.api; +import java.util.HashSet; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.seibel.lod.core.ModInfo; +import com.seibel.lod.core.enums.WorldType; +import com.seibel.lod.core.enums.config.DistanceGenerationMode; import com.seibel.lod.core.objects.lod.LodDimension; import com.seibel.lod.core.objects.math.Mat4f; import com.seibel.lod.core.render.GLProxy; import com.seibel.lod.core.render.LodRenderer; import com.seibel.lod.core.util.DetailDistanceUtil; import com.seibel.lod.core.util.SingletonHandler; +import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory; +import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; +import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper; +import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper; /** * This holds the methods that should be called @@ -52,6 +60,7 @@ public class ClientApi private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class); private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class); private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class); + private static final IWrapperFactory WRAPPER_FACTORY = SingletonHandler.get(IWrapperFactory.class); private static final EventApi EVENT_API = EventApi.INSTANCE; /** @@ -69,14 +78,27 @@ public class ClientApi } + + private HashSet toBeLoaded = null; - + // TODO: Fix it + @Deprecated + public void clientChunkLoadEvent(IChunkWrapper chunk, IWorldWrapper world) + { + //EventApi.INSTANCE.chunkLoadEvent(chunk, world.getDimensionType()); + //ClientApi.LOGGER.info("ChunkLoadEvent called for "+ (world.getWorldType() == WorldType.ClientWorld ? "clientLevel" : "serverLevel"), new RuntimeException()); + + if (toBeLoaded == null) toBeLoaded = new HashSet(); + //toBeLoaded.add(WRAPPER_FACTORY.createChunkPos(chunk.getChunkPosX(), chunk.getChunkPosZ())); + } + + private HashSet lastFrame = new HashSet(); public void renderLods(Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks) { // comment out when creating a release applyConfigOverrides(); - + // clear any out of date objects MC.clearFrameObjectCache(); @@ -85,8 +107,19 @@ public class ClientApi // only run the first time setup once if (!firstTimeSetupComplete) firstFrameSetup(); - - + + IWorldWrapper world = MC.getWrappedClientWorld(); + HashSet chunks = MC_RENDER.getVanillaRenderedChunks(); + if (chunks != null) { + for (AbstractChunkPosWrapper pos : chunks) { + if (lastFrame.contains(pos)) continue; + IChunkWrapper chunk = world.tryGetChunk(pos); + if (chunk == null) continue; + ApiShared.lodBuilder.generateLodNodeDirect(chunk, ApiShared.lodWorld, + world.getDimensionType(), DistanceGenerationMode.FULL, true); + } + } + lastFrame = chunks; if (!MC.playerExists() || ApiShared.lodWorld.getIsWorldNotLoaded()) return; @@ -98,6 +131,8 @@ public class ClientApi EVENT_API.viewDistanceChangedEvent(); EVENT_API.playerMoveEvent(lodDim); + + lodDim.cutRegionNodesAsync(MC.getPlayerBlockPos().getX(), MC.getPlayerBlockPos().getZ()); lodDim.expandOrLoadRegionsAsync(MC.getPlayerBlockPos().getX(), MC.getPlayerBlockPos().getZ()); diff --git a/src/main/java/com/seibel/lod/core/api/EventApi.java b/src/main/java/com/seibel/lod/core/api/EventApi.java index 57e831a2e..a965366d7 100644 --- a/src/main/java/com/seibel/lod/core/api/EventApi.java +++ b/src/main/java/com/seibel/lod/core/api/EventApi.java @@ -19,6 +19,8 @@ package com.seibel.lod.core.api; +import java.util.HashSet; + import org.lwjgl.glfw.GLFW; import com.seibel.lod.core.builders.lodBuilding.LodBuilder; @@ -34,6 +36,8 @@ import com.seibel.lod.core.util.DetailDistanceUtil; import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.util.SingletonHandler; import com.seibel.lod.core.util.ThreadMapUtil; +import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory; +import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper; @@ -66,8 +70,12 @@ public class EventApi { } - - + + @Deprecated + public void chunkLoadEvent(IChunkWrapper chunk, IDimensionTypeWrapper dimType) + { + //ApiShared.lodBuilder.generateLodNodeAsync(chunk, ApiShared.lodWorld, dimType, DistanceGenerationMode.FULL, true); + } //=============// @@ -94,11 +102,6 @@ public class EventApi // world events // //==============// - public void chunkLoadEvent(IChunkWrapper chunk, IDimensionTypeWrapper dimType) - { - ApiShared.lodBuilder.generateLodNodeAsync(chunk, ApiShared.lodWorld, dimType, DistanceGenerationMode.FULL, true); - } - public void worldSaveEvent() { ApiShared.lodWorld.saveAllDimensions(false); // Do an async save. @@ -109,7 +112,8 @@ public class EventApi /** This is also called when a new dimension loads */ public void worldLoadEvent(IWorldWrapper world) { - ClientApi.LOGGER.info("WorldLoadEvent called here for "+ (world.getWorldType() == WorldType.ClientWorld ? "clientLevel" : "serverLevel"), new RuntimeException()); + ClientApi.LOGGER.info("WorldLoadEvent called here for "+ (world.getWorldType() == WorldType.ClientWorld ? + "clientLevel" : "serverLevel"), new RuntimeException()); // Always ignore ServerWorld event if (world.getWorldType() == WorldType.ServerWorld) return; isCurrentlyOnSinglePlayerServer = MC.hasSinglePlayerServer(); diff --git a/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java index bdb6f0370..e1f1dc0b3 100644 --- a/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java @@ -142,6 +142,52 @@ public class LodBuilder }); lodGenThreadPool.execute(thread); } + + public void generateLodNodeDirect(IChunkWrapper chunk, LodWorld lodWorld, IDimensionTypeWrapper dim, DistanceGenerationMode generationMode, boolean override) + { + if (lodWorld == null || lodWorld.getIsWorldNotLoaded()) + return; + + // don't try to create an LOD object + // if for some reason we aren't + // given a valid chunk object + if (chunk == null) + return; + + //noinspection GrazieInspection + try + { + // we need a loaded client world in order to + // get the textures for blocks + if (MC.getWrappedClientWorld() == null) + return; + + // don't try to generate LODs if the user isn't in the world anymore + // (this happens a lot when the user leaves a world/server) + if (!MC.hasSinglePlayerServer() && !MC.connectedToServer()) + return; + + // make sure the dimension exists + LodDimension lodDim; + if (lodWorld.getLodDimension(dim) == null) + { + lodDim = new LodDimension(dim, lodWorld, defaultDimensionWidthInRegions); + lodWorld.addLodDimension(lodDim); + } + else + { + lodDim = lodWorld.getLodDimension(dim); + } + generateLodNodeFromChunk(lodDim, chunk, new LodBuilderConfig(generationMode), override); + } + catch (IllegalArgumentException | NullPointerException e) + { + e.printStackTrace(); + // if the world changes while LODs are being generated + // they will throw errors as they try to access things that no longer + // exist. + } + } /** * Creates a LodNode for a chunk in the given world. diff --git a/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/IWorldWrapper.java b/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/IWorldWrapper.java index ba6214e62..6726d1a56 100644 --- a/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/IWorldWrapper.java +++ b/src/main/java/com/seibel/lod/core/wrapperInterfaces/world/IWorldWrapper.java @@ -23,6 +23,8 @@ import java.io.File; import com.seibel.lod.core.enums.WorldType; import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; +import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; +import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; /** * Can be either a Server world or a Client world. @@ -60,5 +62,7 @@ public interface IWorldWrapper /** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */ File getSaveFolder() throws UnsupportedOperationException; + default IChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {return null;} + }