diff --git a/dependencies.gradle b/dependencies.gradle index 03e1f5dc0..bb83def33 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -116,4 +116,6 @@ dependencies { testImplementation("org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209") compileOnly("mega:fluidlogged-mc1.7.10:0.1.2") + + compileOnly("com.cardinalstar.cubicchunks:CubicChunks1710:99.99.99:dev") } diff --git a/src/main/java/com/gtnewhorizons/angelica/compat/ModStatus.java b/src/main/java/com/gtnewhorizons/angelica/compat/ModStatus.java index 98e8c9e59..b0c86a50a 100644 --- a/src/main/java/com/gtnewhorizons/angelica/compat/ModStatus.java +++ b/src/main/java/com/gtnewhorizons/angelica/compat/ModStatus.java @@ -1,12 +1,14 @@ package com.gtnewhorizons.angelica.compat; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import com.gtnewhorizons.angelica.compat.backhand.BackhandReflectionCompat; +import com.gtnewhorizons.angelica.compat.cubicchunks.CubicChunksDelegate; import com.gtnewhorizons.angelica.helpers.LoadControllerHelper; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.versioning.DefaultArtifactVersion; import mods.battlegear2.Battlegear; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; public class ModStatus { public static final Logger LOGGER = LogManager.getLogger("ModCompat"); @@ -33,6 +35,7 @@ public class ModStatus { public static boolean isThaumicHorizonsLoaded; public static boolean isBaublesLoaded; public static boolean isFluidLoggedLoaded; + public static boolean isCubicChunksLoaded; public static void preInit(){ isBackhandLoaded = Loader.isModLoaded("backhand"); @@ -53,6 +56,7 @@ public static void preInit(){ isThaumicHorizonsLoaded = Loader.isModLoaded("ThaumicHorizons"); isBaublesLoaded = Loader.isModLoaded("Baubles"); isFluidLoggedLoaded = Loader.isModLoaded("fluidlogged"); + isCubicChunksLoaded = Loader.isModLoaded("cubicchunks"); isHoloInventoryLoaded = Loader.isModLoaded("holoinventory"); @@ -71,5 +75,9 @@ public static void preInit(){ isNEIDMetadataExtended = true; } } + + if (isCubicChunksLoaded) { + CubicChunksDelegate.init(); + } } } diff --git a/src/main/java/com/gtnewhorizons/angelica/compat/cubicchunks/CubicChunksAPI.java b/src/main/java/com/gtnewhorizons/angelica/compat/cubicchunks/CubicChunksAPI.java new file mode 100644 index 000000000..fc2f75d02 --- /dev/null +++ b/src/main/java/com/gtnewhorizons/angelica/compat/cubicchunks/CubicChunksAPI.java @@ -0,0 +1,26 @@ +package com.gtnewhorizons.angelica.compat.cubicchunks; + +import net.minecraft.world.World; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +import com.cardinalstar.cubicchunks.api.IColumn; +import com.cardinalstar.cubicchunks.api.ICube; +import com.cardinalstar.cubicchunks.world.cube.Cube; +import com.cardinalstar.cubicchunks.world.cube.ICubeProviderInternal; + +public class CubicChunksAPI { + + public static ExtendedBlockStorage getCubeStorage(World world, int x, int y, int z) { + Cube cube = ((ICubeProviderInternal) world.getChunkProvider()).getLoadedCube(x, y, z); + + if (cube == null || cube.isEmpty()) return null; + + return cube.getStorage(); + } + + public static int[] getLoadedCubeLevelsInColumn(World world, int chunkX, int chunkZ) { + IColumn column = (IColumn) world.getChunkFromChunkCoords(chunkX, chunkZ); + + return column.getLoadedCubes().stream().mapToInt(ICube::getY).toArray(); + } +} diff --git a/src/main/java/com/gtnewhorizons/angelica/compat/cubicchunks/CubicChunksDelegate.java b/src/main/java/com/gtnewhorizons/angelica/compat/cubicchunks/CubicChunksDelegate.java new file mode 100644 index 000000000..ec152ed3c --- /dev/null +++ b/src/main/java/com/gtnewhorizons/angelica/compat/cubicchunks/CubicChunksDelegate.java @@ -0,0 +1,41 @@ +package com.gtnewhorizons.angelica.compat.cubicchunks; + +import net.minecraft.client.Minecraft; + +import com.cardinalstar.cubicchunks.modcompat.angelica.AngelicaInterop; +import com.cardinalstar.cubicchunks.modcompat.angelica.IAngelicaDelegate; +import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTrackerHolder; +import me.jellysquid.mods.sodium.client.render.chunk.map.IChunkTracker; + +public class CubicChunksDelegate implements IAngelicaDelegate { + + public static final CubicChunksDelegate INSTANCE = new CubicChunksDelegate(); + + public static void init() { + AngelicaInterop.setDelegate(INSTANCE); + } + + private static IChunkTracker getTracker() { + return ChunkTrackerHolder.get(Minecraft.getMinecraft().theWorld); + } + + @Override + public void onColumnLoaded(int chunkX, int chunkZ) { + getTracker().onChunkAdded(chunkX, chunkZ); + } + + @Override + public void onColumnUnloaded(int chunkX, int chunkZ) { + getTracker().onChunkRemoved(chunkX, chunkZ); + } + + @Override + public void onCubeLoaded(int cubeX, int cubeY, int cubeZ) { + getTracker().onCubeAdded(cubeX, cubeY, cubeZ); + } + + @Override + public void onCubeUnloaded(int cubeX, int cubeY, int cubeZ) { + getTracker().onCubeRemoved(cubeX, cubeY, cubeZ); + } +} diff --git a/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkOcclusionData.java b/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkOcclusionData.java index 4ed46a3d5..d6b80adde 100644 --- a/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkOcclusionData.java +++ b/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkOcclusionData.java @@ -1,10 +1,10 @@ package com.gtnewhorizons.angelica.compat.mojang; -import net.minecraftforge.common.util.ForgeDirection; - import java.util.BitSet; import java.util.Set; +import net.minecraftforge.common.util.ForgeDirection; + public class ChunkOcclusionData { private static final int DIRECTION_COUNT = ForgeDirection.values().length; private final BitSet visibility; diff --git a/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkSectionPos.java b/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkSectionPos.java index 943313a32..9e71343d7 100644 --- a/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkSectionPos.java +++ b/src/main/java/com/gtnewhorizons/angelica/compat/mojang/ChunkSectionPos.java @@ -1,8 +1,10 @@ package com.gtnewhorizons.angelica.compat.mojang; -import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; import org.joml.Vector3i; +import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; +import com.gtnewhorizon.gtnhlib.util.CoordinatePacker; + // See if we can merge/mixin/extend ChunkPosition maybe? public class ChunkSectionPos extends Vector3i { @@ -25,11 +27,7 @@ public static ChunkSectionPos from(BlockPos pos) { } public static long asLong(int x, int y, int z) { - long l = 0L; - l |= ((long)x & 4194303L) << 42; - l |= ((long)y & 1048575L) << 0; - l |= ((long)z & 4194303L) << 20; - return l; + return CoordinatePacker.pack(x, y, z); } public static int getLocalCoord(int coord) { diff --git a/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java b/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java index ca763f07b..b083bcbe3 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/gui/SodiumGameOptionPages.java @@ -1,8 +1,21 @@ package me.jellysquid.mods.sodium.client.gui; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.settings.GameSettings; + +import org.lwjgl.opengl.Display; + +import com.cardinalstar.cubicchunks.api.compat.CubicChunksVideoSettings; import com.google.common.collect.ImmutableList; +import com.gtnewhorizons.angelica.compat.ModStatus; import com.gtnewhorizons.angelica.config.AngelicaConfig; import com.gtnewhorizons.angelica.glsm.GLStateManager; +import cpw.mods.fml.common.Optional.Method; import jss.notfine.core.Settings; import jss.notfine.core.SettingsManager; import me.flashyreese.mods.reeses_sodium_options.client.gui.ReeseSodiumVideoOptionsScreen; @@ -20,19 +33,12 @@ import me.jellysquid.mods.sodium.client.gui.options.named.LightingQuality; import me.jellysquid.mods.sodium.client.gui.options.named.ParticleMode; import me.jellysquid.mods.sodium.client.gui.options.storage.AngelicaOptionsStorage; +import me.jellysquid.mods.sodium.client.gui.options.storage.CubicChunksOptionStorage; import me.jellysquid.mods.sodium.client.gui.options.storage.MinecraftOptionsStorage; import me.jellysquid.mods.sodium.client.gui.options.storage.SodiumOptionsStorage; import me.jellysquid.mods.sodium.client.render.chunk.backends.multidraw.MultidrawChunkRenderBackend; import net.coderbot.iris.Iris; import net.coderbot.iris.gui.option.IrisVideoSettings; -import net.minecraft.client.Minecraft; -import net.minecraft.client.resources.I18n; -import net.minecraft.client.settings.GameSettings; -import org.lwjgl.opengl.Display; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; public class SodiumGameOptionPages { private static final SodiumOptionsStorage sodiumOpts = new SodiumOptionsStorage(); @@ -52,6 +58,10 @@ public static OptionPage general() { .setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD) .build()); + if (ModStatus.isCubicChunksLoaded) { + firstGroupBuilder.add(getCCVerticalViewDistance()); + } + if(AngelicaConfig.enableIris) { final OptionImpl maxShadowDistanceSlider = OptionImpl.createBuilder(int.class, vanillaOpts) .setName(I18n.format("options.iris.shadowDistance")) @@ -455,4 +465,25 @@ public static OptionPage performance() { return new OptionPage(I18n.format("sodium.options.pages.performance"), ImmutableList.copyOf(groups)); } + + @Method(modid = "cubicchunks") + private static OptionImpl getCCVerticalViewDistance() { + CubicChunksOptionStorage storage = new CubicChunksOptionStorage(); + + return OptionImpl.createBuilder(int.class, storage) + .setName(I18n.format("sodium.options.cc.vertical_view_distance.name")) + .setTooltip(I18n.format("sodium.options.cc.vertical_view_distance.tooltip")) + .setControl(option -> new SliderControl( + option, + CubicChunksVideoSettings.getMinVerticalViewDistance(), + CubicChunksVideoSettings.getMaxVerticalViewDistance(), + 1, + ControlValueFormatter.quantity("options.chunks"))) + .setBinding( + (options, value) -> options.verticalViewDistance = value, + options -> options.verticalViewDistance) + .setImpact(OptionImpact.HIGH) + .setFlags(OptionFlag.REQUIRES_RENDERER_RELOAD) + .build(); + } } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/gui/options/storage/CubicChunksOptionStorage.java b/src/main/java/me/jellysquid/mods/sodium/client/gui/options/storage/CubicChunksOptionStorage.java new file mode 100644 index 000000000..68524a9bb --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/gui/options/storage/CubicChunksOptionStorage.java @@ -0,0 +1,22 @@ +package me.jellysquid.mods.sodium.client.gui.options.storage; + +import com.cardinalstar.cubicchunks.api.compat.CubicChunksVideoSettings; + +public class CubicChunksOptionStorage implements OptionStorage { + + public static class CubicChunksOptions { + public int verticalViewDistance = CubicChunksVideoSettings.getVerticalViewDistance(); + } + + private final CubicChunksOptions options = new CubicChunksOptions(); + + @Override + public CubicChunksOptions getData() { + return options; + } + + @Override + public void save() { + CubicChunksVideoSettings.setVerticalViewDistance(options.verticalViewDistance); + } +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/SodiumWorldRenderer.java b/src/main/java/me/jellysquid/mods/sodium/client/render/SodiumWorldRenderer.java index 6a37c9623..1086cc3ee 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/SodiumWorldRenderer.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/SodiumWorldRenderer.java @@ -21,7 +21,6 @@ import me.jellysquid.mods.sodium.client.render.chunk.backends.oneshot.ChunkRenderBackendOneshot; import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData; import me.jellysquid.mods.sodium.client.render.chunk.format.DefaultModelVertexFormats; -import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTracker; import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTrackerHolder; import me.jellysquid.mods.sodium.client.render.chunk.passes.BlockRenderPass; import me.jellysquid.mods.sodium.client.render.pipeline.context.ChunkRenderCacheShared; @@ -266,7 +265,7 @@ public void updateChunks(Camera camera, Frustrum frustum, boolean hasForcedFrust private void processChunkEvents() { var tracker = ChunkTrackerHolder.get(this.world); - tracker.forEachEvent(this.chunkRenderManager::onChunkAdded, this.chunkRenderManager::onChunkRemoved); + tracker.forEachEvent(this.chunkRenderManager); } /** @@ -330,7 +329,8 @@ private void initRenderer() { this.chunkRenderManager = new ChunkRenderManager<>(this, this.chunkRenderBackend, this.world, this.renderDistance); var tracker = ChunkTrackerHolder.get(this.world); - ChunkTracker.forEachChunk(tracker.getReadyChunks(), this.chunkRenderManager::onChunkAdded); + + tracker.forAllReady(this.chunkRenderManager); } private static ChunkRenderBackend createChunkRenderBackend(RenderDevice device, SodiumGameOptions options, ChunkVertexType vertexFormat) { diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderColumn.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderColumn.java index 5871ef8e2..0ad551ae2 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderColumn.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderColumn.java @@ -5,17 +5,23 @@ import static com.gtnewhorizon.gtnhlib.client.renderer.cel.model.quad.properties.ModelQuadFacing.NEG_Z; import static com.gtnewhorizon.gtnhlib.client.renderer.cel.model.quad.properties.ModelQuadFacing.POS_X; import static com.gtnewhorizon.gtnhlib.client.renderer.cel.model.quad.properties.ModelQuadFacing.POS_Z; - +import java.util.Collection; import net.minecraftforge.common.util.ForgeDirection; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import lombok.Getter; + public class ChunkRenderColumn { - @SuppressWarnings("unchecked") - private final ChunkRenderContainer[] renders = new ChunkRenderContainer[16]; + private final Int2ObjectMap> renders = new Int2ObjectOpenHashMap<>(); @SuppressWarnings("unchecked") private final ChunkRenderColumn[] adjacent = new ChunkRenderColumn[6]; - private final int x, z; + @Getter + private final int x; + @Getter + private final int z; public ChunkRenderColumn(int x, int z) { this.x = x; @@ -34,22 +40,19 @@ public ChunkRenderColumn getAdjacentColumn(ForgeDirection dir) { } public void setRender(int y, ChunkRenderContainer render) { - this.renders[y] = render; - } - - public ChunkRenderContainer getRender(int y) { - if (y < 0 || y >= this.renders.length) { - return null; + if (render == null) { + this.renders.remove(y); + } else { + this.renders.put(y, render); } - return this.renders[y]; } - public int getX() { - return this.x; + public ChunkRenderContainer getRender(int y) { + return this.renders.get(y); } - public int getZ() { - return this.z; + public Collection> getAllRenders() { + return this.renders.values(); } public boolean areNeighborsPresent() { diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java index f083c4fca..47b244ec8 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/ChunkRenderManager.java @@ -1,5 +1,21 @@ package me.jellysquid.mods.sodium.client.render.chunk; +import java.util.ArrayDeque; +import java.util.Collection; +import java.util.Deque; +import java.util.concurrent.CompletableFuture; + +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import net.minecraftforge.common.util.ForgeDirection; + +import org.joml.Vector3d; + +import com.cardinalstar.cubicchunks.api.CCAPI; +import com.gtnewhorizons.angelica.compat.ModStatus; +import com.gtnewhorizons.angelica.compat.cubicchunks.CubicChunksAPI; import com.gtnewhorizons.angelica.compat.mojang.Camera; import com.gtnewhorizons.angelica.compat.mojang.ChunkPos; import com.gtnewhorizons.angelica.compat.toremove.MatrixStack; @@ -36,17 +52,6 @@ import me.jellysquid.mods.sodium.common.util.collections.FutureDequeDrain; import net.coderbot.iris.shadows.ShadowRenderingState; import net.coderbot.iris.sodium.shadow_map.SwappableChunkRenderManager; -import net.minecraft.client.multiplayer.WorldClient; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.chunk.storage.ExtendedBlockStorage; -import net.minecraftforge.common.util.ForgeDirection; -import org.joml.Vector3d; - -import java.util.ArrayDeque; -import java.util.Collection; -import java.util.Deque; -import java.util.concurrent.CompletableFuture; public class ChunkRenderManager implements ChunkStatusListener, SwappableChunkRenderManager { /** @@ -354,7 +359,7 @@ private void addEntitiesToRenderLists(ChunkRenderContainer render) { Collection tileEntities = render.getData().getTileEntities(); this.visibleTileEntities.addAll(tileEntities); } - + public ChunkRenderContainer getRender(int x, int y, int z) { ChunkRenderColumn column = this.columns.get(ChunkPos.toLong(x, z)); @@ -402,6 +407,16 @@ public void onChunkRemoved(int x, int z) { this.unloadChunk(x, z); } + @Override + public void onCubeAdded(int x, int y, int z) { + loadCube(x, y, z); + } + + @Override + public void onCubeRemoved(int x, int y, int z) { + unloadCube(x, y, z); + } + private void loadChunk(int x, int z) { ChunkRenderColumn column = new ChunkRenderColumn<>(x, z); ChunkRenderColumn prev; @@ -433,27 +448,30 @@ private void loadSections(ChunkRenderColumn column) { int x = column.getX(); int z = column.getZ(); - for (int y = 0; y < 16; y++) { - ChunkRenderContainer render = this.createChunkRender(column, x, y, z); - column.setRender(y, render); + if (ModStatus.isCubicChunksLoaded) { + for (ExtendedBlockStorage ebs : CCAPI.getLoadedBlockStorages(world.getChunkFromChunkCoords(x, z))) { + int y = ebs.yBase >> 4; - this.culler.onSectionLoaded(x, y, z, render.getId()); - } - } - - private void unloadSections(ChunkRenderColumn column) { - int x = column.getX(); - int z = column.getZ(); + ChunkRenderContainer render = this.createChunkRender(column, x, y, z); + column.setRender(y, render); - for (int y = 0; y < 16; y++) { - ChunkRenderContainer render = column.getRender(y); + this.culler.onSectionLoaded(x, y, z, render.getId()); + } + } else { + for (int y = 0; y < 16; y++) { + ChunkRenderContainer render = this.createChunkRender(column, x, y, z); + column.setRender(y, render); - if (render != null) { - this.unloadQueue.enqueue(render); - this.renders.remove(render.getId()); + this.culler.onSectionLoaded(x, y, z, render.getId()); } + } + } - this.culler.onSectionUnloaded(x, y, z); + private void unloadSections(ChunkRenderColumn column) { + for (ChunkRenderContainer render : column.getAllRenders()) { + this.unloadQueue.enqueue(render); + this.renders.remove(render.getId()); + this.culler.onSectionUnloaded(column.getX(), render.getChunkY(), column.getZ()); } } @@ -489,9 +507,36 @@ private ChunkRenderColumn getColumn(int x, int z) { return this.columns.get(ChunkPos.toLong(x, z)); } + public void loadCube(int x, int y, int z) { + ChunkRenderColumn column = this.columns.get(ChunkPos.toLong(x, z)); + + if (column == null) return; + + ChunkRenderContainer render = this.createChunkRender(column, x, y, z); + column.setRender(y, render); + + this.culler.onSectionLoaded(x, y, z, render.getId()); + } + + public void unloadCube(int x, int y, int z) { + ChunkRenderColumn column = this.columns.get(ChunkPos.toLong(x, z)); + + if (column == null) return; + + column.setRender(y, null); + + this.culler.onSectionUnloaded(x, y, z); + } + private ChunkRenderContainer createChunkRender(ChunkRenderColumn column, int x, int y, int z) { ChunkRenderContainer render = new ChunkRenderContainer<>(this.backend, this.renderer, x, y, z, column); - final ExtendedBlockStorage array = this.world.getChunkFromChunkCoords(x, z).getBlockStorageArray()[y]; + final ExtendedBlockStorage array; + + if (ModStatus.isCubicChunksLoaded) { + array = CubicChunksAPI.getCubeStorage(this.world, x, y, z); + } else { + array = this.world.getChunkFromChunkCoords(x, z).getBlockStorageArray()[y]; + } if (array == null || array.isEmpty()) { render.setData(ChunkRenderData.EMPTY); diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphCuller.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphCuller.java index ee71255e7..52217cc59 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphCuller.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphCuller.java @@ -1,6 +1,16 @@ package me.jellysquid.mods.sodium.client.render.chunk.cull.graph; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import net.minecraft.block.Block; +import net.minecraft.util.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; + import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; +import com.gtnewhorizons.angelica.compat.ModStatus; import com.gtnewhorizons.angelica.compat.mojang.Camera; import com.gtnewhorizons.angelica.compat.mojang.ChunkOcclusionData; import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos; @@ -9,14 +19,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import me.jellysquid.mods.sodium.client.render.chunk.cull.ChunkCuller; import me.jellysquid.mods.sodium.client.util.math.FrustumExtended; -import net.minecraft.block.Block; -import net.minecraft.util.MathHelper; -import net.minecraft.world.World; -import net.minecraftforge.common.util.ForgeDirection; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; public class ChunkGraphCuller implements ChunkCuller { private final Long2ObjectMap nodes = new Long2ObjectOpenHashMap<>(); @@ -100,7 +102,11 @@ private void initSearch(Camera camera, FrustumExtended frustum, int frame, boole this.visible.add(rootNode); } else { - chunkY = MathHelper.clamp_int(origin.getY() >> 4, 0, 15); + chunkY = origin.getY() >> 4; + + if (!ModStatus.isCubicChunksLoaded) { + chunkY = MathHelper.clamp_int(chunkY, 0, 15); + } final List bestNodes = new ArrayList<>(); diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphNode.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphNode.java index 7a3416ada..83d901210 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphNode.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/cull/graph/ChunkGraphNode.java @@ -1,10 +1,11 @@ package me.jellysquid.mods.sodium.client.render.chunk.cull.graph; +import net.minecraftforge.common.util.ForgeDirection; + import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; import com.gtnewhorizons.angelica.compat.mojang.ChunkOcclusionData; import me.jellysquid.mods.sodium.client.render.chunk.data.ChunkRenderData; import me.jellysquid.mods.sodium.client.util.math.FrustumExtended; -import net.minecraftforge.common.util.ForgeDirection; public class ChunkGraphNode { private static final long DEFAULT_VISIBILITY_DATA = calculateVisibilityData(ChunkRenderData.EMPTY.getOcclusionData()); diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkStatus.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkStatus.java deleted file mode 100644 index 648486cf3..000000000 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkStatus.java +++ /dev/null @@ -1,7 +0,0 @@ -package me.jellysquid.mods.sodium.client.render.chunk.map; - -public class ChunkStatus { - public static final int FLAG_HAS_BLOCK_DATA = 1; - public static final int FLAG_HAS_LIGHT_DATA = 2; - public static final int FLAG_ALL = FLAG_HAS_BLOCK_DATA | FLAG_HAS_LIGHT_DATA; -} \ No newline at end of file diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTracker.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTracker.java index 167ac2739..6e9525522 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTracker.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTracker.java @@ -1,125 +1,21 @@ package me.jellysquid.mods.sodium.client.render.chunk.map; -import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongCollection; -import it.unimi.dsi.fastutil.longs.LongOpenHashSet; -import it.unimi.dsi.fastutil.longs.LongSet; -import it.unimi.dsi.fastutil.longs.LongSets; -import net.minecraft.world.ChunkCoordIntPair; +import com.gtnewhorizons.angelica.compat.ModStatus; -public class ChunkTracker implements ClientChunkEventListener { - private final Long2IntOpenHashMap chunkStatus = new Long2IntOpenHashMap(); - private final LongOpenHashSet chunkReady = new LongOpenHashSet(); +public class ChunkTracker { - private final LongSet unloadQueue = new LongOpenHashSet(); - private final LongSet loadQueue = new LongOpenHashSet(); + private static volatile IChunkTracker tracker; - public ChunkTracker() { - - } - - @Override - public void updateMapCenter(int chunkX, int chunkZ) { - - } - - @Override - public void updateLoadDistance(int loadDistance) { - - } - - @Override - public void onChunkStatusAdded(int x, int z, int flags) { - var key = ChunkCoordIntPair.chunkXZ2Int(x, z); - - var prev = this.chunkStatus.get(key); - var cur = prev | flags; - - if (prev == cur) { - return; - } - - this.chunkStatus.put(key, cur); - - this.updateNeighbors(x, z); - } - - @Override - public void onChunkStatusRemoved(int x, int z, int flags) { - var key = ChunkCoordIntPair.chunkXZ2Int(x, z); - - var prev = this.chunkStatus.get(key); - int cur = prev & ~flags; - - if (prev == cur) { - return; - } - - if (cur == this.chunkStatus.defaultReturnValue()) { - this.chunkStatus.remove(key); - } else { - this.chunkStatus.put(key, cur); - } - - this.updateNeighbors(x, z); - } - - private void updateNeighbors(int x, int z) { - for (int ox = -1; ox <= 1; ox++) { - for (int oz = -1; oz <= 1; oz++) { - this.updateMerged(ox + x, oz + z); - } - } - } - - private void updateMerged(int x, int z) { - long key = ChunkCoordIntPair.chunkXZ2Int(x, z); - - int flags = this.chunkStatus.get(key); - - for (int ox = -1; ox <= 1; ox++) { - for (int oz = -1; oz <= 1; oz++) { - flags &= this.chunkStatus.get(ChunkCoordIntPair.chunkXZ2Int(ox + x, oz + z)); - } - } - - if (flags == ChunkStatus.FLAG_ALL) { - if (this.chunkReady.add(key) && !this.unloadQueue.remove(key)) { - this.loadQueue.add(key); - } - } else { - if (this.chunkReady.remove(key) && !this.loadQueue.remove(key)) { - this.unloadQueue.add(key); + public synchronized static IChunkTracker getTracker() { + if (tracker == null) { + if (ModStatus.isCubicChunksLoaded) { + tracker = new CubicChunkTracker(); + } else { + tracker = new VanillaChunkTracker(); } } - } - - public LongCollection getReadyChunks() { - return LongSets.unmodifiable(this.chunkReady); - } - public void forEachEvent(ChunkEventHandler loadEventHandler, ChunkEventHandler unloadEventHandler) { - forEachChunk(this.unloadQueue, unloadEventHandler); - this.unloadQueue.clear(); - - forEachChunk(this.loadQueue, loadEventHandler); - this.loadQueue.clear(); + return tracker; } - public static void forEachChunk(LongCollection queue, ChunkEventHandler handler) { - var iterator = queue.iterator(); - - while (iterator.hasNext()) { - var pos = iterator.nextLong(); - - var x = (int)(pos & 4294967295L); - var z = (int)((pos >> 32L) & 4294967295L); - - handler.apply(x, z); - } - } - - public interface ChunkEventHandler { - void apply(int x, int z); - } } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java index 4610a9533..4a2aec2c1 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ChunkTrackerHolder.java @@ -3,9 +3,9 @@ import net.minecraft.client.multiplayer.WorldClient; public interface ChunkTrackerHolder { - static ChunkTracker get(WorldClient world) { + static IChunkTracker get(WorldClient world) { return ((ChunkTrackerHolder) world).sodium$getTracker(); } - ChunkTracker sodium$getTracker(); + IChunkTracker sodium$getTracker(); } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java index 60e524426..b3a8e4eff 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/ClientChunkEventListener.java @@ -1,10 +1,10 @@ package me.jellysquid.mods.sodium.client.render.chunk.map; public interface ClientChunkEventListener { - void updateMapCenter(int chunkX, int chunkZ); - void updateLoadDistance(int loadDistance); + void onChunkAdded(int x, int z); + void onChunkRemoved(int x, int z); - void onChunkStatusAdded(int x, int z, int flags); - void onChunkStatusRemoved(int x, int z, int flags); + void onCubeAdded(int x, int y, int z); + void onCubeRemoved(int x, int y, int z); } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/CubicChunkTracker.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/CubicChunkTracker.java new file mode 100644 index 000000000..529745f24 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/CubicChunkTracker.java @@ -0,0 +1,157 @@ +package me.jellysquid.mods.sodium.client.render.chunk.map; + +import net.minecraft.world.ChunkCoordIntPair; + +import net.minecraftforge.common.util.ForgeDirection; + +import com.gtnewhorizon.gtnhlib.util.CoordinatePacker; +import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import me.jellysquid.mods.sodium.client.world.ChunkStatusListener; + +public class CubicChunkTracker implements IChunkTracker { + + private final LongOpenHashSet chunkPresence = new LongOpenHashSet(); + private final LongOpenHashSet cubePresence = new LongOpenHashSet(); + + private final LongOpenHashSet loadedChunks = new LongOpenHashSet(); + private final LongOpenHashSet loadedCubes = new LongOpenHashSet(); + + private final Long2ObjectOpenHashMap chunkStateChanges = new Long2ObjectOpenHashMap<>(); + private final Long2ObjectOpenHashMap cubeStateChanges = new Long2ObjectOpenHashMap<>(); + + @Override + public synchronized void onChunkAdded(int x, int z) { + long key = ChunkCoordIntPair.chunkXZ2Int(x, z); + + if (chunkPresence.add(key)) { + chunkStateChanges.put(key, State.LOAD_PENDING); + } + } + + @Override + public synchronized void onChunkRemoved(int x, int z) { + long key = ChunkCoordIntPair.chunkXZ2Int(x, z); + + if (chunkPresence.remove(key)) { + chunkStateChanges.put(key, State.UNLOAD_PENDING); + } + } + + @Override + public synchronized void onCubeAdded(int x, int y, int z) { + long key = CoordinatePacker.pack(x, y, z); + + if (cubePresence.add(key)) { + this.updateCubeNeighbors(x, y, z); + } + } + + @Override + public synchronized void onCubeRemoved(int x, int y, int z) { + long key = CoordinatePacker.pack(x, y, z); + + if (cubePresence.remove(key)) { + this.updateCubeNeighbors(x, y, z); + } + } + + private void updateCubeNeighbors(int x, int y, int z) { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + this.updateCubesMerged(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ); + } + } + + private boolean isCubePresent(int x, int y, int z) { + return cubePresence.contains(CoordinatePacker.pack(x, y, z)); + } + + private void updateCubesMerged(int x, int y, int z) { + boolean canRender = isCubePresent(x, y, z); + + if (canRender) { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + if (!isCubePresent(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ)) { + canRender = false; + break; + } + } + } + + long key = CoordinatePacker.pack(x, y, z); + + boolean isRendering = loadedCubes.contains(key); + + if (isRendering != canRender) { + if (canRender) { + cubeStateChanges.put(key, State.LOAD_PENDING); + } else { + cubeStateChanges.put(key, State.UNLOAD_PENDING); + } + } + } + + @Override + public synchronized void forAllReady(ChunkStatusListener listener) { + loadedChunks.forEach((long k) -> { + int x = unpackChunkX(k); + int z = unpackChunkZ(k); + + listener.onChunkAdded(x, z); + }); + + loadedCubes.forEach((long k) -> { + int x = CoordinatePacker.unpackX(k); + int y = CoordinatePacker.unpackY(k); + int z = CoordinatePacker.unpackZ(k); + + listener.onCubeAdded(x, y, z); + }); + } + + @Override + public synchronized void forEachEvent(ChunkStatusListener listener) { + Long2ObjectMaps.fastForEach(chunkStateChanges, e -> { + int x = unpackChunkX(e.getLongKey()); + int z = unpackChunkZ(e.getLongKey()); + + if (e.getValue() == State.LOAD_PENDING) { + loadedChunks.add(e.getLongKey()); + listener.onChunkAdded(x, z); + } else { + loadedChunks.remove(e.getLongKey()); + listener.onChunkRemoved(x, z); + } + }); + + chunkStateChanges.clear(); + + Long2ObjectMaps.fastForEach( + cubeStateChanges, e -> { + int x = CoordinatePacker.unpackX(e.getLongKey()); + int y = CoordinatePacker.unpackY(e.getLongKey()); + int z = CoordinatePacker.unpackZ(e.getLongKey()); + + if (e.getValue() == State.LOAD_PENDING) { + if (loadedCubes.add(e.getLongKey())) { + listener.onCubeAdded(x, y, z); + } + } else { + if (loadedCubes.remove(e.getLongKey())) { + listener.onCubeRemoved(x, y, z); + } + } + }); + + cubeStateChanges.clear(); + } + + private static int unpackChunkZ(long pos) { + return (int) ((pos >>> 32L) & 0xFFFFFFFFL); + } + + private static int unpackChunkX(long pos) { + return (int) (pos & 0xFFFFFFFFL); + } +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/IChunkTracker.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/IChunkTracker.java new file mode 100644 index 000000000..a2fcc1341 --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/IChunkTracker.java @@ -0,0 +1,18 @@ +package me.jellysquid.mods.sodium.client.render.chunk.map; + +import com.gtnewhorizons.angelica.compat.ModStatus; +import me.jellysquid.mods.sodium.client.world.ChunkStatusListener; + +public interface IChunkTracker extends ClientChunkEventListener { + + void forAllReady(ChunkStatusListener listener); + void forEachEvent(ChunkStatusListener listener); + + static IChunkTracker newInstance() { + if (ModStatus.isCubicChunksLoaded) { + return new CubicChunkTracker(); + } else { + return new VanillaChunkTracker(); + } + } +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/State.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/State.java new file mode 100644 index 000000000..e3f6bb6cc --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/State.java @@ -0,0 +1,6 @@ +package me.jellysquid.mods.sodium.client.render.chunk.map; + +enum State { + LOAD_PENDING, + UNLOAD_PENDING +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/VanillaChunkTracker.java b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/VanillaChunkTracker.java new file mode 100644 index 000000000..2478a763c --- /dev/null +++ b/src/main/java/me/jellysquid/mods/sodium/client/render/chunk/map/VanillaChunkTracker.java @@ -0,0 +1,115 @@ +package me.jellysquid.mods.sodium.client.render.chunk.map; + +import net.minecraft.world.ChunkCoordIntPair; +import net.minecraftforge.common.util.ForgeDirection; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMaps; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import me.jellysquid.mods.sodium.client.world.ChunkStatusListener; + +public class VanillaChunkTracker implements IChunkTracker { + + private final LongOpenHashSet chunkPresence = new LongOpenHashSet(); + + private final LongOpenHashSet loadedChunks = new LongOpenHashSet(); + + private final Long2ObjectOpenHashMap chunkStateChanges = new Long2ObjectOpenHashMap<>(); + + @Override + public void onChunkAdded(int x, int z) { + long key = ChunkCoordIntPair.chunkXZ2Int(x, z); + + if (chunkPresence.add(key)) { + this.updateChunkNeighbors(x, z); + } + } + + @Override + public void onChunkRemoved(int x, int z) { + long key = ChunkCoordIntPair.chunkXZ2Int(x, z); + + if (chunkPresence.remove(key)) { + this.updateChunkNeighbors(x, z); + } + } + + @Override + public void onCubeAdded(int x, int y, int z) { + throw new UnsupportedOperationException("Cubes should never be added to the vanilla tracker"); + } + + @Override + public void onCubeRemoved(int x, int y, int z) { + throw new UnsupportedOperationException("Cubes should never be removed from the vanilla tracker"); + } + + private void updateChunkNeighbors(int x, int z) { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + this.updateChunksMerged(x + dir.offsetX, z + dir.offsetZ); + } + } + + private boolean isChunkPresent(int chunkX, int chunkZ) { + return chunkPresence.contains(ChunkCoordIntPair.chunkXZ2Int(chunkX, chunkZ)); + } + + private void updateChunksMerged(int x, int z) { + long key = ChunkCoordIntPair.chunkXZ2Int(x, z); + + boolean canRender = isChunkPresent(x, z); + + if (canRender) { + for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + if (!isChunkPresent(x + dir.offsetX, z + dir.offsetZ)) { + canRender = false; + break; + } + } + } + + boolean isRendering = loadedChunks.contains(key); + + if (isRendering != canRender) { + if (canRender) { + chunkStateChanges.put(key, State.LOAD_PENDING); + } else { + chunkStateChanges.put(key, State.UNLOAD_PENDING); + } + } + } + + public void forAllReady(ChunkStatusListener listener) { + loadedChunks.forEach((long k) -> { + int x = unpackChunkX(k); + int z = unpackChunkZ(k); + + listener.onChunkAdded(x, z); + }); + } + + public void forEachEvent(ChunkStatusListener listener) { + Long2ObjectMaps.fastForEach(chunkStateChanges, e -> { + int x = unpackChunkX(e.getLongKey()); + int z = unpackChunkZ(e.getLongKey()); + + if (e.getValue() == State.LOAD_PENDING) { + loadedChunks.add(e.getLongKey()); + listener.onChunkAdded(x, z); + } else { + loadedChunks.remove(e.getLongKey()); + listener.onChunkRemoved(x, z); + } + }); + + chunkStateChanges.clear(); + } + + private static int unpackChunkZ(long pos) { + return (int) ((pos >> 32L) & 0xFFFFFFFFL); + } + + private static int unpackChunkX(long pos) { + return (int) (pos & 0xFFFFFFFFL); + } +} diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/ChunkStatusListener.java b/src/main/java/me/jellysquid/mods/sodium/client/world/ChunkStatusListener.java index 7cdbbc4c3..8965d0d85 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/ChunkStatusListener.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/world/ChunkStatusListener.java @@ -17,4 +17,20 @@ public interface ChunkStatusListener { * @param z The z-coordinate of the unloaded chunk */ void onChunkRemoved(int x, int z); + + /** + * Called after a cube is added to the world and loaded. + * @param x The x-coordinate of the loaded cube + * @param y The y-coordinate of the loaded cube + * @param z The z-coordinate of the loaded cube + */ + void onCubeAdded(int x, int y, int z); + + /** + * Called after a cube is removed from the world and unloaded. + * @param x The x-coordinate of the loaded cube + * @param y The y-coordinate of the loaded cube + * @param z The z-coordinate of the loaded cube + */ + void onCubeRemoved(int x, int y, int z); } diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java b/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java index 7073f0544..1d8bb0b12 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/world/WorldSlice.java @@ -3,6 +3,7 @@ import com.gtnewhorizon.gtnhlib.client.renderer.cel.model.quad.properties.ModelQuadFacing; import com.gtnewhorizons.angelica.api.IBlockAccessExtended; import com.gtnewhorizons.angelica.compat.ModStatus; +import com.gtnewhorizons.angelica.compat.cubicchunks.CubicChunksAPI; import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos; import com.gtnewhorizons.angelica.compat.mojang.CompatMathHelper; import com.gtnewhorizons.angelica.dynamiclights.DynamicLights; @@ -100,7 +101,13 @@ public class WorldSlice implements IBlockAccessExtended, FLBlockAccess { public static ChunkRenderContext prepare(World world, ChunkSectionPos origin, ClonedChunkSectionCache sectionCache) { final Chunk chunk = world.getChunkFromChunkCoords(origin.x, origin.z); - final ExtendedBlockStorage section = chunk.getBlockStorageArray()[origin.y]; + final ExtendedBlockStorage section; + + if (ModStatus.isCubicChunksLoaded) { + section = CubicChunksAPI.getCubeStorage(world, origin.x, origin.y, origin.z); + } else { + section = chunk.getBlockStorageArray()[origin.y]; + } // If the chunk section is absent or empty, simply terminate now. There will never be anything in this chunk // section to render, so we need to signal that a chunk render task shouldn't created. This saves a considerable diff --git a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java index de0ec7f03..06d983124 100644 --- a/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java +++ b/src/main/java/me/jellysquid/mods/sodium/client/world/cloned/ClonedChunkSection.java @@ -3,6 +3,7 @@ import com.falsepattern.endlessids.mixin.helpers.ChunkBiomeHook; import com.gtnewhorizons.angelica.compat.ExtendedBlockStorageExt; import com.gtnewhorizons.angelica.compat.ModStatus; +import com.gtnewhorizons.angelica.compat.cubicchunks.CubicChunksAPI; import com.gtnewhorizons.angelica.compat.mojang.ChunkSectionPos; import it.unimi.dsi.fastutil.shorts.Short2ObjectMap; import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap; @@ -52,7 +53,13 @@ public void init(ChunkSectionPos pos) { throw new RuntimeException("Couldn't retrieve chunk at " + pos.toChunkPos()); } - ExtendedBlockStorage section = getChunkSection(chunk, pos); + ExtendedBlockStorage section; + + if (ModStatus.isCubicChunksLoaded) { + section = CubicChunksAPI.getCubeStorage(world, pos.x, pos.y, pos.z); + } else { + section = getChunkSection(chunk, pos); + } if (section == null /*WorldChunk.EMPTY_SECTION*/ /*ChunkSection.isEmpty(section)*/) { section = EMPTY_SECTION; diff --git a/src/main/resources/assets/angelica/lang/en_US.lang b/src/main/resources/assets/angelica/lang/en_US.lang index 9749ea6b6..568acaf21 100644 --- a/src/main/resources/assets/angelica/lang/en_US.lang +++ b/src/main/resources/assets/angelica/lang/en_US.lang @@ -14,6 +14,8 @@ sodium.options.pages.performance=Performance sodium.options.pages.advanced=Advanced sodium.options.view_distance.tooltip=The render distance controls how far away terrain will be rendered. Shorter distances mean that less terrain will be rendered, improving frame rates. sodium.options.simulation_distance.tooltip=The simulation distance controls how far away terrain and entities will be loaded and ticked. Shorter distances can reduce the internal server's load and may improve frame rates. +sodium.options.cc.vertical_view_distance.name=Vertical View Distance +sodium.options.cc.vertical_view_distance.tooltip=The vertical view distance controls the vertical range within which cubes will be loaded, centered on the player. Shorter distances mean that less terrain will be rendered, improving frame rates. sodium.options.brightness.tooltip=Controls the brightness (gamma) of the game. sodium.options.clouds.name=Clouds sodium.options.clouds.tooltip=Controls whether or not clouds will be visible. diff --git a/src/main/resources/assets/sodium/shaders/chunk_gl20.f.glsl b/src/main/resources/assets/sodium/shaders/chunk_gl20.f.glsl index c9649f24c..2ebcf77b4 100644 --- a/src/main/resources/assets/sodium/shaders/chunk_gl20.f.glsl +++ b/src/main/resources/assets/sodium/shaders/chunk_gl20.f.glsl @@ -28,7 +28,7 @@ uniform float u_FogEnd; // (end - dist) / (end - start) float getFogFactor() { - return (u_FogEnd - v_FragDistance) / u_FogLength; + return max(1.0, (u_FogEnd - v_FragDistance) / u_FogLength); } #endif diff --git a/src/mixin/java/com/gtnewhorizons/angelica/mixins/early/sodium/MixinWorldClient.java b/src/mixin/java/com/gtnewhorizons/angelica/mixins/early/sodium/MixinWorldClient.java index 654b7adf3..e542d0a77 100644 --- a/src/mixin/java/com/gtnewhorizons/angelica/mixins/early/sodium/MixinWorldClient.java +++ b/src/mixin/java/com/gtnewhorizons/angelica/mixins/early/sodium/MixinWorldClient.java @@ -1,29 +1,32 @@ package com.gtnewhorizons.angelica.mixins.early.sodium; -import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkStatus; -import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTracker; -import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTrackerHolder; import net.minecraft.client.multiplayer.WorldClient; + import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import me.jellysquid.mods.sodium.client.render.chunk.map.ChunkTrackerHolder; +import me.jellysquid.mods.sodium.client.render.chunk.map.IChunkTracker; + @Mixin(WorldClient.class) public class MixinWorldClient implements ChunkTrackerHolder { - private final ChunkTracker angelica$tracker = new ChunkTracker(); + @Unique + private final IChunkTracker angelica$tracker = IChunkTracker.newInstance(); @Inject(method = "doPreChunk", at = @At("TAIL")) private void sodium$loadChunk(int x, int z, boolean load, CallbackInfo ci) { if(load) { - this.angelica$tracker.onChunkStatusAdded(x, z, ChunkStatus.FLAG_ALL); + this.angelica$tracker.onChunkAdded(x, z); } else { - this.angelica$tracker.onChunkStatusRemoved(x, z, ChunkStatus.FLAG_ALL); + this.angelica$tracker.onChunkRemoved(x, z); } } @Override - public ChunkTracker sodium$getTracker() { + public IChunkTracker sodium$getTracker() { return this.angelica$tracker; } }