Created
December 11, 2020 18:12
-
-
Save CorgiTaco/d380b52933eff0d6e900be8f3c066972 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.github.opencubicchunks.cubicchunks.chunk; | |
import java.util.Collection; | |
import java.util.Collections; | |
import java.util.Map; | |
import com.google.common.collect.Maps; | |
import io.github.opencubicchunks.cubicchunks.utils.Coords; | |
import io.github.opencubicchunks.cubicchunks.world.DummyHeightmap; | |
import net.minecraft.core.BlockPos; | |
import net.minecraft.world.level.ChunkPos; | |
import net.minecraft.world.level.LevelHeightAccessor; | |
import net.minecraft.world.level.block.state.BlockState; | |
import net.minecraft.world.level.chunk.ChunkAccess; | |
import net.minecraft.world.level.chunk.LevelChunk; | |
import net.minecraft.world.level.chunk.LevelChunkSection; | |
import net.minecraft.world.level.chunk.ProtoChunk; | |
import net.minecraft.world.level.chunk.UpgradeData; | |
import net.minecraft.world.level.levelgen.Heightmap; | |
import net.minecraft.world.level.material.FluidState; | |
import org.jetbrains.annotations.Nullable; | |
public class NoiseAndSurfaceBuilderHelper extends ProtoChunk { | |
private final ChunkAccess[] delegates; | |
private int columnX; | |
private int columnZ; | |
private final Map<Heightmap.Types, Heightmap> heightmaps; | |
public NoiseAndSurfaceBuilderHelper(IBigCube delegate, IBigCube delegateAbove) { | |
super(delegate.getCubePos().asChunkPos(), UpgradeData.EMPTY, new HeightAccessor(delegate.getCubePos().minCubeY(), IBigCube.DIAMETER_IN_BLOCKS * 2)); | |
this.delegates = new ChunkAccess[2]; | |
this.delegates[0] = (ChunkAccess) delegate; | |
this.delegates[1] = (ChunkAccess) delegateAbove; | |
this.heightmaps = Maps.newEnumMap(Heightmap.Types.class); | |
} | |
public void moveColumn(int columnX, int columnZ) { | |
this.columnX = columnX; | |
this.columnZ = columnZ; | |
} | |
public void applySections() { | |
for (int idx = 0; idx < this.getSections().length; idx++) { | |
int sectionY = getSectionYFromSectionIndex(idx); | |
IBigCube delegateCube = (IBigCube) getDelegateFromSectionY(sectionY); | |
assert delegateCube != null; | |
delegateCube.getCubeSections()[Coords.sectionToIndex(columnX, sectionY, columnZ)] = getSections()[idx]; | |
} | |
} | |
@Override public Heightmap getOrCreateHeightmapUnprimed(Heightmap.Types type) { | |
return this.heightmaps.computeIfAbsent(type, (typex) -> { | |
return new DummyHeightmap(this, typex); //Essentially do nothing here. | |
}); | |
} | |
@Override public ChunkPos getPos() { | |
return ((IBigCube) delegates[0]).getCubePos().asChunkPos(columnX, columnZ); | |
} | |
@Override public int getHeight(Heightmap.Types type, int x, int z) { | |
int blockX = Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getX(), x) + (columnX * 16); | |
int blockZ = Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getX(), z) + (columnZ * 16); | |
return ((IBigCube) delegates[0]).getCubeLocalHeight(type, blockX, blockZ); | |
} | |
@Override public LevelChunkSection getOrCreateSection(int sectionIndex) { | |
LevelChunkSection[] cubeSections = this.getSections(); | |
if (cubeSections[sectionIndex] == LevelChunk.EMPTY_SECTION) { | |
cubeSections[sectionIndex] = new LevelChunkSection(this.getSectionYFromSectionIndex(sectionIndex)); | |
} | |
return cubeSections[sectionIndex]; | |
} | |
@Override public Collection<Map.Entry<Heightmap.Types, Heightmap>> getHeightmaps() { | |
return Collections.unmodifiableSet(this.heightmaps.entrySet()); | |
} | |
@Override public int getSectionIndex(int y) { | |
if (((IBigCube) delegates[0]).getCubePos().getX() == 2 && ((IBigCube) delegates[1]).getCubePos().getZ() == 5 && y < -1000) { | |
String s = ""; | |
} | |
return Coords.blockToCubeLocalSection(y) + IBigCube.DIAMETER_IN_SECTIONS * getDelegateIndex(Coords.blockToCube(y)); | |
} | |
@Override public int getMinBuildHeight() { | |
return ((IBigCube) delegates[0]).getCubePos().minCubeY(); | |
} | |
@Override public int getSectionYFromSectionIndex(int sectionIndex) { | |
int delegateIDX = sectionIndex / IBigCube.DIAMETER_IN_SECTIONS; | |
int cubeSectionIDX = sectionIndex % IBigCube.DIAMETER_IN_SECTIONS; | |
return getDelegateByIndex(delegateIDX).getCubePos().asSectionPos().getY() + cubeSectionIDX; | |
} | |
@Override public int getHeight() { | |
return IBigCube.DIAMETER_IN_BLOCKS * 2; | |
} | |
@Override public void addLight(BlockPos pos) { | |
//TODO | |
} | |
@Override public BlockState getBlockState(BlockPos pos) { | |
BlockPos blockPos = new BlockPos(Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getX(), pos.getX()) + (columnX * 16), pos.getY(), | |
Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getZ(), pos.getZ()) + (columnZ * 16)); | |
return ((IBigCube) delegates[0]).getBlockState(blockPos); | |
} | |
@Override public FluidState getFluidState(BlockPos pos) { | |
BlockPos blockPos = new BlockPos(Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getX(), pos.getX()) + (columnX * 16), pos.getY(), | |
Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getZ(), pos.getZ() + (columnZ * 16))); | |
return delegates[0].getFluidState(blockPos); | |
} | |
@Nullable @Override public BlockState setBlockState(BlockPos pos, BlockState state, boolean moved) { | |
BlockPos blockPos = new BlockPos(Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getX(), pos.getX()) + (columnX * 16), pos.getY(), | |
Coords.localToBlock(((IBigCube) delegates[0]).getCubePos().getZ(), pos.getZ() + (columnZ * 16))); | |
return ((IBigCube) delegates[0]).setBlock(blockPos, state, moved); | |
} | |
/********Helpers********/ | |
@Nullable public ChunkAccess getDelegateCube(int cubeY) { | |
int minCubeY = ((IBigCube) delegates[0]).getCubePos().getY(); | |
int maxCubeY = ((IBigCube) delegates[1]).getCubePos().getY(); | |
if (cubeY < minCubeY) { | |
throw SectionSizeCubeAccessWrapper.StopGeneratingThrowable.INSTANCE; | |
} | |
if (cubeY > maxCubeY) { | |
return null; | |
} | |
return delegates[cubeY - minCubeY]; | |
} | |
public int getDelegateIndex(int y) { | |
int minY = ((IBigCube) delegates[0]).getCubePos().getY(); | |
if (y < minY) { | |
return -1; | |
} | |
if (y > ((IBigCube) delegates[1]).getCubePos().getY()) { | |
return -1; | |
} | |
return y - minY; | |
} | |
@Nullable public ChunkAccess getDelegateFromBlockY(int blockY) { | |
return getDelegateCube(Coords.blockToCube(blockY)); | |
} | |
@Nullable public ChunkAccess getDelegateFromSectionY(int sectionIDX) { | |
return getDelegateCube(Coords.sectionToCube(sectionIDX)); | |
} | |
@SuppressWarnings("unchecked") public <T extends ChunkAccess & IBigCube> T getDelegateByIndex(int idx) { | |
return (T) delegates[idx]; | |
} | |
public static class StopGeneratingThrowable extends RuntimeException { | |
public static final SectionSizeCubeAccessWrapper.StopGeneratingThrowable INSTANCE = new SectionSizeCubeAccessWrapper.StopGeneratingThrowable(); | |
public StopGeneratingThrowable() { | |
super("Stop the surface builder"); | |
} | |
} | |
private static class HeightAccessor implements LevelHeightAccessor { | |
private final int minBuildHeight; | |
private final int height; | |
public HeightAccessor(int minBuildHeight, int height) { | |
this.minBuildHeight = minBuildHeight; | |
this.height = height; | |
} | |
@Override public int getHeight() { | |
return height; | |
} | |
@Override public int getMinBuildHeight() { | |
return minBuildHeight; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment