Initial release
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
package de.nicolasklier.custom_structures.structures;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import de.nicolasklier.custom_structures.CustomStructures;
|
||||
import de.nicolasklier.custom_structures.events.PlayerTick;
|
||||
import de.nicolasklier.custom_structures.utils.PerlinNoise;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.Material;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Direction.Axis;
|
||||
|
||||
public class Generations {
|
||||
|
||||
List<Block> fence_whitelist = new ArrayList<>();
|
||||
|
||||
public Generations() {
|
||||
fence_whitelist.add(Blocks.OAK_FENCE);
|
||||
fence_whitelist.add(Blocks.BIRCH_FENCE);
|
||||
fence_whitelist.add(Blocks.SPRUCE_FENCE);
|
||||
fence_whitelist.add(Blocks.JUNGLE_FENCE);
|
||||
}
|
||||
|
||||
public void spawnStaircase(BlockPos at, StaircaseOptions options) {
|
||||
Map<BlockPos, BlockState> placeQueue = new HashMap<>();
|
||||
MinecraftClient instance = MinecraftClient.getInstance();
|
||||
int length = options.height * options.stretch * (options.mirror ? 2 : 1);
|
||||
|
||||
Random rng = new Random();
|
||||
PerlinNoise noise = null;
|
||||
|
||||
int y = -(options.weight);
|
||||
int step = 0;
|
||||
|
||||
if (options.noise != null) {
|
||||
noise = new PerlinNoise(rng, options.noise.roughness, length, length);
|
||||
noise.initialise();
|
||||
}
|
||||
|
||||
// Final length is height times stretch factor. If mirroring is enabled, then it will be twice as long.
|
||||
int x = 0;
|
||||
boolean isMirroring = y > options.height * options.stretch;
|
||||
|
||||
if (step >= options.stretch) {
|
||||
step = 0;
|
||||
|
||||
// Check if we already reached our final height. If yes, go downwards
|
||||
if (isMirroring) {
|
||||
y -= 1;
|
||||
} else {
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int z = 0; z < options.width; z++) {
|
||||
boolean isNextHeight = true;
|
||||
|
||||
if (options.stretch > 1) {
|
||||
if (isMirroring) {
|
||||
isNextHeight = step == 0;
|
||||
} else {
|
||||
isNextHeight = step + 1 == options.stretch;
|
||||
}
|
||||
}
|
||||
|
||||
Block block = Blocks.COBBLESTONE;
|
||||
|
||||
// Build supporting fence
|
||||
if (x % options.fenceVerticalDensity == 0 && y > 0) {
|
||||
// From left to right
|
||||
for (int z2 = 0; z2 <= options.width; z2 += (options.width - 1) / options.fenceHorizontalDensity) {
|
||||
// Place fence manually on ground because the loop below offsets by one.
|
||||
placeQueue.put(at.add(x + 1, 0, z2), getRandomFance(rng));
|
||||
|
||||
int y2 = y - options.weight;
|
||||
while (true) {
|
||||
Material mat = instance.getServer().getOverworld().getBlockState(new BlockPos(x, y2, z2)).getMaterial();
|
||||
if (mat == Material.AIR || mat == Material.WATER) {
|
||||
placeQueue.put(at.add(x, y2, z2), getRandomFance(rng));
|
||||
placeQueue.put(at.add(x + 1, y2 + 1, z2), getRandomFance(rng));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
y2--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean putStair = false;
|
||||
|
||||
// Decide if there should be mossy cobblestone or glass. If yes, then don't put a stair there.
|
||||
if (rng.nextFloat() < options.chanceMossyCobblestone / 100f) {
|
||||
block = Blocks.MOSSY_COBBLESTONE;
|
||||
} else if (rng.nextFloat() < options.chanceGlass / 100f) {
|
||||
block = Blocks.GLASS;
|
||||
} else {
|
||||
putStair = true;
|
||||
}
|
||||
|
||||
// Build actual block
|
||||
for (int j = 0; j < options.weight; j++) {
|
||||
// Building imperfection
|
||||
if (rng.nextFloat() < 0.001) continue;
|
||||
|
||||
placeQueue.put(at.add(x, y + j, z), block.getDefaultState());
|
||||
}
|
||||
|
||||
Direction facing = isMirroring ? Direction.WEST : Direction.EAST;
|
||||
|
||||
// Build stair or not
|
||||
if (putStair && isNextHeight) {
|
||||
BlockState stairState = Blocks.COBBLESTONE_STAIRS.getDefaultState().with(Properties.HORIZONTAL_FACING, facing);
|
||||
|
||||
if (isMirroring)
|
||||
stairState = stairState.with(Properties.HORIZONTAL_FACING, facing);
|
||||
|
||||
if (rng.nextFloat() < options.chanceSlap / 100f) {
|
||||
placeQueue.put(at.add(x, y + options.weight, z), Blocks.SMOOTH_STONE_SLAB.getDefaultState());
|
||||
} else {
|
||||
CustomStructures.LOGGER.info("Noise [" + x + ", " + y + "]: " + noise.getValueAt(x, y + options.weight));
|
||||
if (noise.getValueAt(x, y + options.weight) < options.chanceWoodStair / 100f) {
|
||||
|
||||
// Override stair as wood stair, copying the facing.
|
||||
stairState = Blocks.OAK_STAIRS.getDefaultState()
|
||||
.with(Properties.HORIZONTAL_FACING, stairState.get(Properties.HORIZONTAL_FACING));
|
||||
} else if (rng.nextFloat() > options.chanceMossyCobblestone / 100f) {
|
||||
stairState = Blocks.MOSSY_COBBLESTONE_STAIRS.getDefaultState()
|
||||
.with(Properties.HORIZONTAL_FACING, stairState.get(Properties.HORIZONTAL_FACING));
|
||||
}
|
||||
|
||||
placeQueue.put(at.add(x, y + options.weight, z), stairState);
|
||||
}
|
||||
} else {
|
||||
if (rng.nextFloat() < 0.04) {
|
||||
placeQueue.put(at.add(x, y + options.weight - 1, z), Blocks.GLOWSTONE.getDefaultState());
|
||||
}
|
||||
}
|
||||
|
||||
// Build wall
|
||||
if ((z == 0 || z == options.width - 1) && options.wallHeight > 0) {
|
||||
for (int y2 = 0; y2 < options.wallHeight; y2++) {
|
||||
placeQueue.put(at.add(x, y + y2 + options.weight, z), Blocks.OAK_PLANKS.getDefaultState());
|
||||
}
|
||||
|
||||
placeQueue.put(at.add(x, y + options.wallHeight + options.weight, z), Blocks.OAK_FENCE.getDefaultState());
|
||||
placeQueue.put(at.add(x, y + options.wallHeight + options.weight + 1, z), Blocks.OAK_FENCE.getDefaultState());
|
||||
placeQueue.put(at.add(x, y + options.wallHeight + options.weight + 2, z), Blocks.OAK_PLANKS.getDefaultState());
|
||||
|
||||
if (isNextHeight) {
|
||||
placeQueue.put(at.add(x, y + options.wallHeight + options.weight + 3, z), Blocks.OAK_STAIRS.getDefaultState()
|
||||
.with(Properties.HORIZONTAL_FACING, facing));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
step++;
|
||||
}
|
||||
|
||||
PlayerTick.queue.putAll(placeQueue);
|
||||
|
||||
Set<BlockPos> set = placeQueue.keySet();
|
||||
List<BlockPos> list = new ArrayList<>(set);
|
||||
//Collections.shuffle(list);
|
||||
PlayerTick.queueKeys = list.iterator();
|
||||
}
|
||||
|
||||
|
||||
private BlockState getRandomFance(Random rng) {
|
||||
return fence_whitelist.get(rng.nextInt(0, fence_whitelist.size() - 1)).getDefaultState();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package de.nicolasklier.custom_structures.structures;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class StaircaseNoiseOptions {
|
||||
|
||||
public float roughness = 0.1f;
|
||||
|
||||
public Random rng = new Random();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package de.nicolasklier.custom_structures.structures;
|
||||
|
||||
public class StaircaseOptions {
|
||||
/**
|
||||
* Width of the staircase on the Z-axis.
|
||||
*/
|
||||
public int width = 21;
|
||||
|
||||
/**
|
||||
* Thickness of the staircase.
|
||||
*/
|
||||
public int weight = 3;
|
||||
|
||||
/**
|
||||
* Height of the staircase on the Y-axis.
|
||||
*/
|
||||
public int height = 32;
|
||||
|
||||
/**
|
||||
* Padding between the support fences vertically (XY-plane).
|
||||
*/
|
||||
public int fenceVerticalDensity = 10;
|
||||
|
||||
/**
|
||||
* Padding between the support fences horizontally (ZY-plane).
|
||||
*/
|
||||
public int fenceHorizontalDensity = 3;
|
||||
|
||||
/**
|
||||
* Height of the wall left & right. Set to 0 to disable this feature.
|
||||
*/
|
||||
public int wallHeight = 2;
|
||||
|
||||
/**
|
||||
* Scratch the staircase along the X-axis.
|
||||
*/
|
||||
public int stretch = 4;
|
||||
|
||||
/**
|
||||
* Mirror staircase when height is reached. This will double your length.
|
||||
*/
|
||||
public boolean mirror = false;
|
||||
|
||||
/**
|
||||
* Value between 0% and 100% being the chance to spawn glass.
|
||||
*/
|
||||
public short chanceGlass = 10;
|
||||
|
||||
/**
|
||||
* Value between 0% and 100% being the chance to spawn glowstone.
|
||||
*/
|
||||
public short chanceGlowstone = 4;
|
||||
|
||||
/**
|
||||
* Value between 0% and 100% being the chance to spawn mossy cobblestone.
|
||||
*/
|
||||
public short chanceMossyCobblestone = 20;
|
||||
|
||||
/**
|
||||
* Value between 0% and 100% being the chance to spawn a slap instead of an stair.
|
||||
*/
|
||||
public short chanceSlap = 5;
|
||||
|
||||
/**
|
||||
* Value between 0% and 100% being the chance to spawn a wooden stair instead of an cobblestone stair.
|
||||
*/
|
||||
public short chanceWoodStair = 50;
|
||||
|
||||
/**
|
||||
* Adds variation to the stretch of the staircase. This will override `stretch`.
|
||||
* To disable this feature set it to null.
|
||||
*/
|
||||
public StaircaseNoiseOptions noise = null;
|
||||
}
|
||||
Reference in New Issue
Block a user