mirror of
https://github.com/chylex/Hardcore-Ender-Expansion-2.git
synced 2025-04-11 03:15:44 +02:00
Add base classes for blob generation
This commit is contained in:
parent
c9ba15aadb
commit
c0df0be37f
src/main/java/chylex/hee/game/world/feature/basic/blobs
@ -0,0 +1,67 @@
|
||||
package chylex.hee.game.world.feature.basic.blobs
|
||||
import chylex.hee.game.world.generation.SegmentedWorld
|
||||
import chylex.hee.game.world.generation.segments.SegmentFull
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.system.collection.WeightedList
|
||||
import chylex.hee.system.collection.WeightedList.Companion.weightedListOf
|
||||
import chylex.hee.system.util.Facing6
|
||||
import chylex.hee.system.util.allInBoxMutable
|
||||
import chylex.hee.system.util.max
|
||||
import net.minecraft.init.Blocks
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import java.util.Random
|
||||
|
||||
class BlobGenerator(private val patterns: WeightedList<BlobPattern>){
|
||||
constructor(pattern: BlobPattern) : this(weightedListOf(1 to pattern))
|
||||
|
||||
private companion object{
|
||||
private val SCAFFOLDING = ModBlocks.SCAFFOLDING.defaultState
|
||||
}
|
||||
|
||||
fun generate(world: SegmentedWorld, rand: Random, pos: BlockPos): Boolean{
|
||||
val pattern = patterns.generateItem(rand)
|
||||
val generator = pattern.pickGenerator(rand)
|
||||
val populators = pattern.pickPopulators(rand)
|
||||
|
||||
val extraSize = populators.fold(BlockPos.ORIGIN){ acc, populator -> acc.max(populator.expandSizeBy) }
|
||||
val allocatedSize = generator.size.expand(extraSize)
|
||||
|
||||
if (!allocatedSize.toBoundingBox(pos).isInside(world.worldSize.toBoundingBox(BlockPos.ORIGIN))){
|
||||
return false
|
||||
}
|
||||
|
||||
val blobWorld = SegmentedWorld(rand, allocatedSize, allocatedSize){ SegmentFull(allocatedSize, SCAFFOLDING) }
|
||||
|
||||
generator.generate(blobWorld, rand)
|
||||
runSmoothingPass(blobWorld, adjacentAirCount = 4)
|
||||
runSmoothingPass(blobWorld, adjacentAirCount = 5)
|
||||
|
||||
for(populator in populators){
|
||||
populator.generate(blobWorld, rand)
|
||||
}
|
||||
|
||||
for(offset in allocatedSize.minPos.allInBoxMutable(allocatedSize.maxPos)){
|
||||
val state = blobWorld.getState(offset)
|
||||
|
||||
if (state !== SCAFFOLDING){
|
||||
world.setState(pos.add(offset), state)
|
||||
}
|
||||
}
|
||||
|
||||
for((offset, trigger) in blobWorld.getTriggers()){
|
||||
world.addTrigger(pos.add(offset), trigger)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun runSmoothingPass(blobWorld: SegmentedWorld, adjacentAirCount: Int){
|
||||
val size = blobWorld.worldSize
|
||||
|
||||
for(pos in size.minPos.allInBoxMutable(size.maxPos)){
|
||||
if (blobWorld.getBlock(pos) === Blocks.END_STONE && Facing6.count { blobWorld.getState(pos.offset(it)) === SCAFFOLDING } >= adjacentAirCount){
|
||||
blobWorld.setState(pos, SCAFFOLDING)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package chylex.hee.game.world.feature.basic.blobs
|
||||
import chylex.hee.system.collection.WeightedList
|
||||
import chylex.hee.system.util.nextInt
|
||||
import java.util.Random
|
||||
|
||||
class BlobPattern private constructor(
|
||||
private val generators: WeightedList<IBlobGenerator>,
|
||||
private val populators: Pair<WeightedList<IBlobPopulator>, ((Random) -> Int)>?
|
||||
){
|
||||
constructor(generators: WeightedList<IBlobGenerator>) : this(generators, null)
|
||||
|
||||
constructor(generators: WeightedList<IBlobGenerator>, populators: WeightedList<IBlobPopulator>, populatorAmount: (Random) -> Int) : this(
|
||||
generators, populators to populatorAmount
|
||||
)
|
||||
|
||||
constructor(generators: WeightedList<IBlobGenerator>, populators: WeightedList<IBlobPopulator>, populatorAmount: IntRange) : this(
|
||||
generators, populators to { rand -> rand.nextInt(populatorAmount.start, populatorAmount.endInclusive) }
|
||||
)
|
||||
|
||||
fun pickGenerator(rand: Random): IBlobGenerator{
|
||||
return generators.generateItem(rand)
|
||||
}
|
||||
|
||||
fun pickPopulators(rand: Random): List<IBlobPopulator>{
|
||||
val (list, amount) = populators ?: return emptyList()
|
||||
|
||||
val remaining = list.mutableCopy()
|
||||
val picked = mutableListOf<IBlobPopulator>()
|
||||
|
||||
repeat(amount(rand)){
|
||||
remaining.removeItem(rand)?.let(picked::add)
|
||||
}
|
||||
|
||||
return picked
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package chylex.hee.game.world.feature.basic.blobs
|
||||
import chylex.hee.game.world.generation.SegmentedWorld
|
||||
import chylex.hee.game.world.util.Size
|
||||
import chylex.hee.system.util.Facing6
|
||||
import chylex.hee.system.util.allInCenteredBoxMutable
|
||||
import chylex.hee.system.util.ceilToInt
|
||||
import chylex.hee.system.util.distanceSqTo
|
||||
import chylex.hee.system.util.square
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.init.Blocks
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import java.util.Random
|
||||
|
||||
interface IBlobGenerator{
|
||||
val size: Size
|
||||
fun generate(world: SegmentedWorld, rand: Random)
|
||||
|
||||
companion object{
|
||||
fun placeBlob(world: SegmentedWorld, center: BlockPos, radius: Double, block: Block = Blocks.END_STONE): Boolean{
|
||||
val offset = radius.ceilToInt()
|
||||
|
||||
if (!world.isInside(center) || Facing6.any { !world.isInside(center.offset(it, offset)) }){
|
||||
return false
|
||||
}
|
||||
|
||||
val radiusSq = square(radius + 0.5)
|
||||
|
||||
for(pos in center.allInCenteredBoxMutable(offset, offset, offset)){
|
||||
if (pos.distanceSqTo(center) <= radiusSq){
|
||||
world.setBlock(pos, block)
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package chylex.hee.game.world.feature.basic.blobs
|
||||
import chylex.hee.game.world.generation.SegmentedWorld
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import java.util.Random
|
||||
|
||||
interface IBlobPopulator{
|
||||
@JvmDefault
|
||||
val expandSizeBy: BlockPos
|
||||
get() = BlockPos.ORIGIN
|
||||
|
||||
fun generate(world: SegmentedWorld, rand: Random)
|
||||
}
|
Loading…
Reference in New Issue
Block a user