diff --git a/build.gradle b/build.gradle index 759b5e7f0..12a1dbb04 100644 --- a/build.gradle +++ b/build.gradle @@ -92,6 +92,12 @@ mixin { } repositories { + maven { + url 'https://www.cursemaven.com' + content { + includeGroup "curse.maven" + } + } maven { name 'tterrag maven' url 'https://maven.tterrag.com/' @@ -101,6 +107,8 @@ repositories { dependencies { minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" + compileOnly fg.deobf("curse.maven:starlight-526854:3559934") + // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings // This allows 'Settings > Build, Execution, and Deployment > Build Tools > Gradle > Build and run using' set to IntelliJ to work correctly diff --git a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunk.java b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunk.java index 925d7516a..ec3bb296f 100644 --- a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunk.java +++ b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunk.java @@ -7,6 +7,10 @@ import java.util.stream.Stream; import javax.annotation.Nullable; +import com.jozufozu.flywheel.util.Mods; + +import ca.spottedleaf.starlight.common.chunk.ExtendedChunk; +import ca.spottedleaf.starlight.common.light.StarLightEngine; import it.unimi.dsi.fastutil.longs.LongSet; import it.unimi.dsi.fastutil.shorts.ShortList; import net.minecraft.core.BlockPos; @@ -48,11 +52,17 @@ public class VirtualChunk extends ChunkAccess { this.x = x; this.z = z; - this.sections = new LevelChunkSection[16]; + int sectionCount = world.getSectionsCount(); + this.sections = new LevelChunkSection[sectionCount]; - for (int i = 0; i < 16; i++) { + for (int i = 0; i < sectionCount; i++) { sections[i] = new VirtualChunkSection(this, i << 4); } + + Mods.STARLIGHT.executeIfInstalled(() -> () -> { + ((ExtendedChunk)this).setBlockNibbles(StarLightEngine.getFilledEmptyLight(this)); + ((ExtendedChunk)this).setSkyNibbles(StarLightEngine.getFilledEmptyLight(this)); + }); } @Override diff --git a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunkSource.java b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunkSource.java index bfef41047..b374260d0 100644 --- a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunkSource.java +++ b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualChunkSource.java @@ -3,8 +3,6 @@ package com.jozufozu.flywheel.core.virtual; import java.util.HashMap; import java.util.function.BooleanSupplier; -import javax.annotation.Nullable; - import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; @@ -22,7 +20,6 @@ public class VirtualChunkSource extends ChunkSource { this.world = world; } - @Nullable @Override public BlockGetter getChunkForLighting(int x, int z) { return getChunk(x, z); @@ -33,7 +30,6 @@ public class VirtualChunkSource extends ChunkSource { return world; } - @Nullable @Override public ChunkAccess getChunk(int x, int z, ChunkStatus status, boolean p_212849_4_) { return getChunk(x, z); diff --git a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java index 7d616c665..fb50c9469 100644 --- a/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java +++ b/src/main/java/com/jozufozu/flywheel/core/virtual/VirtualRenderWorld.java @@ -29,7 +29,9 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkSource; +import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.entity.LevelEntityGetter; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.lighting.LevelLightEngine; @@ -45,17 +47,24 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld { public final Set spannedSections = new HashSet<>(); private final BlockPos.MutableBlockPos scratch = new BlockPos.MutableBlockPos(); - public final LevelLightEngine lighter; - public final VirtualChunkSource chunkSource; + protected final Level level; + protected final LevelLightEngine lighter; + protected final VirtualChunkSource chunkSource; + protected final LevelEntityGetter entityGetter = new VirtualLevelEntityGetter<>(); - protected Level level; - - protected LevelEntityGetter entityGetter = new VirtualLevelEntityGetter<>(); + protected final int height; + protected final int minBuildHeight; public VirtualRenderWorld(Level level) { + this(level, level.getHeight(), level.getMinBuildHeight()); + } + + public VirtualRenderWorld(Level level, int height, int minBuildHeight) { super((WritableLevelData) level.getLevelData(), level.dimension(), level.dimensionType(), level::getProfiler, true, false, 0); this.level = level; + this.height = height; + this.minBuildHeight = minBuildHeight; this.chunkSource = new VirtualChunkSource(this); this.lighter = new LevelLightEngine(chunkSource, true, false); } @@ -87,6 +96,16 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld { // MEANINGFUL OVERRIDES + @Override + public int getHeight() { + return height; + } + + @Override + public int getMinBuildHeight() { + return minBuildHeight; + } + @Override public ChunkSource getChunkSource() { return chunkSource; @@ -262,4 +281,60 @@ public class VirtualRenderWorld extends Level implements FlywheelWorld { @Override public void sendBlockUpdated(BlockPos pos, BlockState oldState, BlockState newState, int flags) {} + // Override Starlight's ExtendedWorld interface methods: + + public LevelChunk getChunkAtImmediately(final int chunkX, final int chunkZ) { + return chunkSource.getChunk(chunkX, chunkZ, false); + } + + public ChunkAccess getAnyChunkImmediately(final int chunkX, final int chunkZ) { + return chunkSource.getChunk(chunkX, chunkZ); + } + + // Intentionally copied from LevelHeightAccessor. Lithium overrides these methods so we need to, too. + + @Override + public int getMaxBuildHeight() { + return this.getMinBuildHeight() + this.getHeight(); + } + + @Override + public int getSectionsCount() { + return this.getMaxSection() - this.getMinSection(); + } + + @Override + public int getMinSection() { + return SectionPos.blockToSectionCoord(this.getMinBuildHeight()); + } + + @Override + public int getMaxSection() { + return SectionPos.blockToSectionCoord(this.getMaxBuildHeight() - 1) + 1; + } + + @Override + public boolean isOutsideBuildHeight(BlockPos pos) { + return this.isOutsideBuildHeight(pos.getY()); + } + + @Override + public boolean isOutsideBuildHeight(int y) { + return y < this.getMinBuildHeight() || y >= this.getMaxBuildHeight(); + } + + @Override + public int getSectionIndex(int y) { + return this.getSectionIndexFromSectionY(SectionPos.blockToSectionCoord(y)); + } + + @Override + public int getSectionIndexFromSectionY(int sectionY) { + return sectionY - this.getMinSection(); + } + + @Override + public int getSectionYFromSectionIndex(int sectionIndex) { + return sectionIndex + this.getMinSection(); + } } diff --git a/src/main/java/com/jozufozu/flywheel/util/Mods.java b/src/main/java/com/jozufozu/flywheel/util/Mods.java new file mode 100644 index 000000000..27c0cb2f2 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/util/Mods.java @@ -0,0 +1,47 @@ +package com.jozufozu.flywheel.util; + +import java.util.Optional; +import java.util.function.Supplier; + +import net.minecraftforge.fml.ModList; + +/** + * For compatibility with and without another mod present, we have to define load conditions of the specific code + */ +public enum Mods { + STARLIGHT("starlight"); + + private final String id; + + Mods(String id) { + this.id = id; + } + + /** + * @return a boolean of whether the mod is loaded or not based on mod id + */ + public boolean isLoaded() { + return ModList.get().isLoaded(id); + } + + /** + * Simple hook to run code if a mod is installed + * @param toRun will be run only if the mod is loaded + * @return Optional.empty() if the mod is not loaded, otherwise an Optional of the return value of the given supplier + */ + public Optional runIfInstalled(Supplier> toRun) { + if (isLoaded()) + return Optional.of(toRun.get().get()); + return Optional.empty(); + } + + /** + * Simple hook to execute code if a mod is installed + * @param toExecute will be executed only if the mod is loaded + */ + public void executeIfInstalled(Supplier toExecute) { + if (isLoaded()) { + toExecute.get().run(); + } + } +}