Skip to content

Instantly share code, notes, and snippets.

@CorgiTaco
Created December 11, 2020 18:12
Show Gist options
  • Save CorgiTaco/d380b52933eff0d6e900be8f3c066972 to your computer and use it in GitHub Desktop.
Save CorgiTaco/d380b52933eff0d6e900be8f3c066972 to your computer and use it in GitHub Desktop.
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