This commit is contained in:
minjaesong
2024-02-03 02:26:58 +09:00
parent d9adbda6f6
commit 93e0c8742a
8 changed files with 391 additions and 221 deletions

View File

@@ -11,8 +11,8 @@
"21";"21";"21";"BLOCK_STONE_MARBLE";"0.1252";"0.1252";"0.1252";"0.1252";"48";"2400";"ROCK";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.1";"ROCK,NATURAL"
# dirts
"32";"32";"32";"BLOCK_DIRT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL"
"33";"32";"32";"BLOCK_GRASS";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
"32";"32";"32";"BLOCK_DIRT";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL,CULTIVABLE"
"33";"32";"32";"BLOCK_GRASS";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"0";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL,CULTIVABLE"
"34";"34";"34";"BLOCK_GRASSWALL";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
"35";"item@basegame:25";"item@basegame:25";"BLOCK_CLAY";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1700";"DIRT";"1";"1";"N/A";"0";"4";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"DIRT,NATURAL"
#"35";"35";"35";"BLOCK_FOLIAGE_GREEN";"0.1252";"0.1252";"0.1252";"0.1252";"24";"1400";"GRSS";"1";"1";"N/A";"0";"0";"16";"0.0000";"0.0000";"0.0000";"0.0000";"N/A";"N/A";"0.0";"GRASS,NATURAL"
Can't render this file because it contains an unexpected character in line 18 and column 2.

Binary file not shown.

View File

@@ -0,0 +1,135 @@
package net.torvald.terrarum.modulebasegame.gameactors
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.worldgenerator.Treegen
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
/**
* Created by minjaesong on 2024-02-03.
*/
open class Cultivable: FixtureBase {
open var currentGrowth = 0f
@Transient var maxGrowth: Int = 0; private set
@Transient open val growthPerTick = 1f
@Transient open val growthRandomness = 0.33333334f
open var growthBonusMult = 1f
override fun canSpawnOnThisFloor(itemID: ItemID) = BlockCodex[itemID].hasTag("CULTIVABLE")
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 2),
nameFun = { " " }
)
constructor(maxGrowth: Int) : super(
BlockBox(BlockBox.NO_COLLISION, 1, 2),
nameFun = { " " }
) {
this.maxGrowth = maxGrowth
}
fun tickGrowthCounter() {
val worldTimeDelta = INGAME.world.worldTime.timeDelta
val rnd = 1f + (((Math.random() * 2.0) - 1.0) * growthRandomness)
currentGrowth += growthPerTick * worldTimeDelta * growthBonusMult * rnd.toFloat()
}
open fun tryToSpawnMaturePlant() {
}
}
/**
* Created by minjaesong on 2024-02-03.
*/
open class SaplingBase(val species: Int) : Cultivable(72000) {
private val variant = (0..3).random()
init {
CommonResourcePool.addToLoadingList("basegame/sprites/saplings.tga") {
TextureRegionPack(ModMgr.getGdxFile("basegame", "sprites/saplings.tga"), 16, 32)
}
CommonResourcePool.loadAll()
makeNewSprite(CommonResourcePool.getAsTextureRegionPack("basegame/sprites/saplings.tga")).let {
it.setRowsAndFrames(4,4)
}
}
override fun update(delta: Float) {
super.update(delta)
// these have to run every frame to make the sprite static
(sprite as SheetSpriteAnimation).currentRow = species
(sprite as SheetSpriteAnimation).currentFrame = variant
if (!flagDespawn) {
tickGrowthCounter()
// printdbg(this, "growth=$currentGrowth/$maxGrowth")
if (currentGrowth >= maxGrowth) {
tryToSpawnMaturePlant()
}
}
}
private var treeHasBeenGrown = false
override fun tryToSpawnMaturePlant() {
if (INGAME.WORLD_UPDATE_TIMER % 3 == 2) {
val size = if (Math.random() < 0.1) 2 else 1
val result = Treegen.plantTree(INGAME.world, intTilewiseHitbox.startX.toInt(), intTilewiseHitbox.endY.toInt() + 1, species, size)
if (result) {
treeHasBeenGrown = true
flagDespawn()
}
}
}
/**
* this function will be called when:
* 1. player removes a sapling that has not yet matured
* 2. the sapling is matured and the tree is about to be spawned
*/
override fun despawn() {
if (canBeDespawned) {
printdbg(this, "despawn at T${INGAME.WORLD_UPDATE_TIMER}: ${nameFun()}")
// printStackTrace(this)
// remove filler block
if (!treeHasBeenGrown) {
forEachBlockbox { x, y, _, _ ->
world!!.setTileTerrain(x, y, Block.AIR, true)
}
}
worldBlockPos = null
mainUI?.dispose()
this.isVisible = false
despawnHook(this)
}
else {
printdbg(this, "failed to despawn at T${INGAME.WORLD_UPDATE_TIMER}: ${nameFun()}")
printdbg(this, "cannot despawn a fixture with non-empty inventory")
}
}
}
class SaplingOak : SaplingBase(0)
class SaplingEbony : SaplingBase(1)
class SaplingBirch : SaplingBase(2)
class SaplingRosewood : SaplingBase(3)

View File

@@ -245,6 +245,13 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
}
}
/**
* Condition for (if the tile is solid) is always implied regardless of this function. See [canSpawnHere0]
*/
open fun canSpawnOnThisFloor(itemID: ItemID): Boolean {
return true
}
fun canSpawnHere(posX0: Int, posY0: Int): Boolean {
val posX = (posX0 - blockBox.width.minus(1).div(2)) fmod world!!.width // width.minus(1) so that spawning position would be same as the ghost's position
val posY = posY0 - blockBox.height + 1
@@ -269,7 +276,11 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
if (spawnNeedsFloor) {
val y = posY + blockBox.height
val xs = posX until posX + blockBox.width
cannotSpawn = cannotSpawn or xs.any { x -> !BlockCodex[world!!.getTileFromTerrain(x, y)].isSolid }
cannotSpawn = cannotSpawn or xs.any { x ->
world!!.getTileFromTerrain(x, y).let {
!BlockCodex[it].isSolid || !canSpawnOnThisFloor(it)
}
}
}
return !cannotSpawn
@@ -297,7 +308,8 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
val posY = posY0 - blockBox.height + 1
if (!canSpawnHere(posX0, posY0)) {
printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
printdbg(this, "cannot spawn fixture1 ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
printStackTrace(this)
return false
}
printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
@@ -314,6 +326,12 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
blockBox.width * TILE_SIZED,
blockBox.height * TILE_SIZED
)
this.intTilewiseHitbox.setFromWidthHeight(
posX.toDouble(),
posY.toDouble(),
blockBox.width.toDouble(),
blockBox.height.toDouble()
)
// actually add this actor into the world
INGAME.queueActorAddition(this)
@@ -399,10 +417,16 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
blockBox.width * TILE_SIZED,
blockBox.height * TILE_SIZED
)
this.intTilewiseHitbox.setFromWidthHeight(
posX.toDouble(),
posY.toDouble(),
blockBox.width.toDouble(),
blockBox.height.toDouble()
)
// check for existing blocks (and fixtures)
if (!canSpawnHere0(posX, posY)) {
printdbg(this, "cannot spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
printdbg(this, "cannot spawn fixture2 ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, has tile collision; xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
return false
}
printdbg(this, "spawn fixture ${nameFun()} at F${INGAME.WORLD_UPDATE_TIMER}, xy=($posX,$posY) tDim=(${blockBox.width},${blockBox.height})")
@@ -471,21 +495,10 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
protected var dropItem = false
/**
* This function MUST BE super-called for make despawn call to work at all.
*/
override fun update(delta: Float) {
// FIXME retrieving fixture by mining relied on a quirk that mining a actorblock would also drop the fixture.
// FIXME since that particular method of operation causes so much problems, it is required to implement the
// FIXME said feature "correctly"
/*if (!flagDespawn && worldBlockPos != null) {
// removal-by-player because player is removing the filler block by pick
// no-flagDespawn check is there to prevent item dropping when externally despawned
// (e.g. picked the fixture up in which case the fixture must not drop itself to the world; it must go into the actor's inventory)
forEachBlockbox { x, y, _, _ ->
if (!BlockCodex[world!!.getTileFromTerrain(x, y)].isActorBlock) {
flagDespawn = true
dropItem = true
}
}
}*/
if (!canBeDespawned) flagDespawn = false // actively deny despawning request if cannot be despawned
if (canBeDespawned && flagDespawn) despawn()
if (canBeDespawned && dropItem) dropSelfAsAnItem()

View File

@@ -0,0 +1,38 @@
package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.gameitems.ItemID
class ItemSeedOak(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingOak") {
override var originalName = "ITEM_SEED_OAK"
override var baseMass = 10.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(0,11)
}
class ItemSeedEbony(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingEbony") {
override var originalName = "ITEM_SEED_EBONY"
override var baseMass = 10.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(1,11)
}
class ItemSeedBirch(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingBirch") {
override var originalName = "ITEM_SEED_BIRCH"
override var baseMass = 10.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(2,11)
}
class ItemSeedRosewood(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.SaplingRosewood") {
override var originalName = "ITEM_SEED_ROSEWOOD"
override var baseMass = 10.0
override val materialId = "OOZE"
override var inventoryCategory = Category.GENERIC
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(3,11)
}

View File

@@ -89,33 +89,6 @@ class ItemLogsRosewood(originalID: ItemID) : OreItemBase(originalID) {
class ItemSeedOak(originalID: ItemID) : OreItemBase(originalID) {
override var originalName = "ITEM_SEED_OAK"
override val materialId = "OOZE"
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(0,11)
}
class ItemSeedEbony(originalID: ItemID) : OreItemBase(originalID) {
override var originalName = "ITEM_SEED_EBONY"
override val materialId = "OOZE"
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(1,11)
}
class ItemSeedBirch(originalID: ItemID) : OreItemBase(originalID) {
override var originalName = "ITEM_SEED_BIRCH"
override val materialId = "OOZE"
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(2,11)
}
class ItemSeedRosewood(originalID: ItemID) : OreItemBase(originalID) {
override var originalName = "ITEM_SEED_ROSEWOOD"
override val materialId = "OOZE"
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(3,11)
}
class OreStick(originalID: ItemID) : OreItemBase(originalID) {
override var originalName = "ITEM_WOOD_STICK"
override val materialId = "WOOD"

View File

@@ -1,10 +1,8 @@
package net.torvald.terrarum.modulebasegame.worldgenerator
import com.sudoplay.joise.Joise
import net.torvald.random.HQRNG
import net.torvald.random.XXHash32
import net.torvald.terrarum.*
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.BlockAddress
@@ -88,13 +86,7 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
val thre = this - ibase
return if (nextDouble(x, y, h) < 1.0 - thre) ibase else ibase + 1
}
private fun nextDouble(x: Int, y: Int, h: Int): Double {
return ((XXHash32.hashGeoCoord(x, y) * 31 + h) and 0xFFFFFF) / 16777216.0
}
private fun nextFloat(x: Int, y: Int, h: Int): Float {
return ((XXHash32.hashGeoCoord(x, y) * 31 + h) and 0xFFFFFF) / 16777216f
}
private fun tryToPlant(xs: IntProgression, ys: Int, grassMap: Array<List<Int>>) {
val treeSpecies = 0
@@ -147,12 +139,12 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
// if there is no grass, grassMap[x] is an empty list
if (treeToSpawn[0] != 0) {
grassMap[plot1].let { if (it.isEmpty()) null else it.takeRand(xs.first + plot1, ys, 1234) }?.let {
plantTree(xs.first + plot1, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
plantTree(world, xs.first + plot1, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
}
}
if (treeToSpawn[1] != 0) {
grassMap[plot2].let { if (it.isEmpty()) null else it.takeRand(xs.first + plot2, ys, 2345) }?.let {
plantTree(xs.first + plot2, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
plantTree(world, xs.first + plot2, it, treeSpecies, 1) // TODO use treeSize from the treeToSpawn
}
}
}
@@ -163,7 +155,7 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
if (treeToSpawn[0] != 0) {
val treeSize = arrayOf(null, 0, 1, 2)[treeToSpawn[0]]
grassMap[plot1].let { if (it.isEmpty()) null else it.takeRand(xs.first + plot1, ys, 4567) }?.let {
plantTree(xs.first + plot1, it, treeSpecies, treeSize!!)
plantTree(world, xs.first + plot1, it, treeSpecies, treeSize!!)
}
}
}
@@ -195,121 +187,126 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
}
// don't use POI -- generate tiles using code for randomisation
/**
* @param y where the grass/dirt tile is
*/
private fun plantTree(x: Int, y: Int, type: Int, size: Int) {
val trunk = "basegame:" + ((if (size <= 1) 64 else 72) + type)
val foliage = "basegame:" + (112 + type)
companion object {
/**
* If a tree cannot be planted on the specified space, `false` will be returned
*
* @param y where the grass/dirt tile is
* @param species 0: oak, 1: ebony, 2: birch, 3: rose
* @param size 0: shrub, 1: normal tree, 2: large tree
*/
fun plantTree(world: GameWorld, x: Int, y: Int, species: Int, size: Int): Boolean {
val trunk = "basegame:" + ((if (size <= 1) 64 else 72) + species)
val foliage = "basegame:" + (112 + species)
var growCnt = 1
if (size == 0) {
val heightSum = 3
var growCnt = 1
if (size == 0) {
val heightSum = 3
// check for minimum height
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
// check for minimum height
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
if (chkM1 || chk0 || chkP1) {
if (chkM1 || chk0 || chkP1) {
// printdbg(this, "Ceiling not tall enough at $x, $y, aborting")
return
}
val stem = 1
val bulb1 = 3 + fudgeN(x, y, 4095823)
// trunk
for (i in 0 until stem) {
for (xi in -1..+1) {
if (xi != 0) {
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
}
else {
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
}
return false
}
growCnt += 1
}
// bulb 1
growCnt = drawBulb(x, y, 3, bulb1, foliage, growCnt)
}
else if (size == 1) {
val heightSum = 5+3+2+1
// check for minimum height
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
if (chkM1 || chk0 || chkP1) {
val stem = 1
val bulb1 = 3 + fudgeN(x, y, 4095823)
// trunk
for (i in 0 until stem) {
for (xi in -1..+1) {
if (xi != 0) {
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
}
else {
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
}
}
growCnt += 1
}
// bulb 1
growCnt = drawBulb(world, x, y, 3, bulb1, foliage, growCnt)
}
else if (size == 1) {
val heightSum = 5 + 3 + 2 + 1
// check for minimum height
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
if (chkM1 || chk0 || chkP1) {
// printdbg(this, "Ceiling not tall enough at $x, $y, aborting")
return
}
return false
}
// roll for dice until we get a height that fits into the given terrain
val stem = 7 + fudgeN(x, y, 7548291, 1530948)
val bulb1 = 4 + fudgeN(x, y, 345098)
val bulb2 = 3 + fudgeN(x, y, 6093481)
val bulb3 = 2 + fudgeN(x, y, 5413879)
// roll for dice until we get a height that fits into the given terrain
val stem = 7 + fudgeN(x, y, 7548291, 1530948)
val bulb1 = 4 + fudgeN(x, y, 345098)
val bulb2 = 3 + fudgeN(x, y, 6093481)
val bulb3 = 2 + fudgeN(x, y, 5413879)
// printdbg(this, "Planting tree at $x, $y; params: $stem, $bulb1, $bulb2, $bulb3")
// trunk
for (i in 0 until stem) {
for (xi in -1..+1) {
if (xi != 0) {
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
}
else {
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
// trunk
for (i in 0 until stem) {
for (xi in -1..+1) {
if (xi != 0) {
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
}
else {
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
}
}
growCnt += 1
}
// bulb base
for (x in x - 2..x + 2) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
// bulb 1
growCnt = drawBulb(world, x, y, 7, bulb1, foliage, growCnt)
// bulb 2
growCnt = drawBulb(world, x, y, 5, bulb2, foliage, growCnt)
// bulb 3
growCnt = drawBulb(world, x, y, 3, bulb3, foliage, growCnt)
}
// bulb base
for (x in x-2..x+2) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
// bulb 1
growCnt = drawBulb(x, y, 7, bulb1, foliage, growCnt)
// bulb 2
growCnt = drawBulb(x, y, 5, bulb2, foliage, growCnt)
// bulb 3
growCnt = drawBulb(x, y, 3, bulb3, foliage, growCnt)
}
else if (size == 2) {
val heightSum = 12+4+3+2+1
// check for minimum height
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP2 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
else if (size == 2) {
val heightSum = 12 + 4 + 3 + 2 + 1
// check for minimum height
val chkM1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chk0 = (1..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP1 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
val chkP2 = (2..heightSum).any { BlockCodex[world.getTileFromTerrain(x, y - it)].isSolid }
if (chkM1 || chk0 || chkP1 || chkP2) {
if (chkM1 || chk0 || chkP1 || chkP2) {
// printdbg(this, "Ceiling not tall enough at $x, $y, aborting")
return
}
return false
}
// roll for dice until we get a height that fits into the given terrain
val stem = 15 + fudgeN(x, y, 14509, 509348, 412098357)
val bulb1 = 5 + fudgeN(x, y, 1254)
val bulb2 = 4 + fudgeN(x, y, 98134)
val bulb3 = 3 + fudgeN(x, y, 123098)
val bulb4 = 2 + fudgeN(x, y, 8712)
// roll for dice until we get a height that fits into the given terrain
val stem = 15 + fudgeN(x, y, 14509, 509348, 412098357)
val bulb1 = 5 + fudgeN(x, y, 1254)
val bulb2 = 4 + fudgeN(x, y, 98134)
val bulb3 = 3 + fudgeN(x, y, 123098)
val bulb4 = 2 + fudgeN(x, y, 8712)
// printdbg(this, "Planting tree at $x, $y; params: $stem, $bulb1, $bulb2, $bulb3, $bulb4")
// soiling
val tl1 = world.getTileFromTerrain(x - 1, y)
val tl2 = world.getTileFromTerrain(x + 1, y)
if (BlockCodex[tl2].hasTag("INCONSEQUENTIAL")) {
world.setTileTerrain(x + 1, y, Block.GRASS, true)
/*
// soiling
val tl1 = world.getTileFromTerrain(x - 1, y)
val tl2 = world.getTileFromTerrain(x + 1, y)
if (BlockCodex[tl2].hasTag("INCONSEQUENTIAL")) {
world.setTileTerrain(x + 1, y, Block.GRASS, true)
/*
Case 1
WW WW
GG. -> GGG
@@ -319,82 +316,94 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
xG. -> xGG
xG. xDG
*/
if (tl1 == Block.GRASS) {
world.setTileTerrain(x, y + 1, Block.DIRT, true)
if (tl1 == Block.GRASS) {
world.setTileTerrain(x, y + 1, Block.DIRT, true)
if (BlockCodex[world.getTileFromTerrain(x + 1, y + 1)].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x + 1, y + 1, Block.DIRT, true)
}
/*
if (BlockCodex[world.getTileFromTerrain(x + 1, y + 1)].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x + 1, y + 1, Block.DIRT, true)
}
/*
Case 2
WW WW
.G. -> .GG
xGx xGx
*/
}
// trunk
for (i in 0 until stem) {
for (xi in -1..+2) {
if (xi !in 0..1) {
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
}
else {
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
}
}
growCnt += 1
}
// bulb base
for (x in x - 2..x + 3) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
for (x in x - 3..x + 4) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
// bulb 1
growCnt = drawBulb(world, x, y, 10, bulb1, foliage, growCnt)
// bulb 2
growCnt = drawBulb(world, x, y, 8, bulb2, foliage, growCnt)
// bulb 3
growCnt = drawBulb(world, x, y, 6, bulb3, foliage, growCnt)
// bulb 4
growCnt = drawBulb(world, x, y, 4, bulb4, foliage, growCnt)
}
// trunk
for (i in 0 until stem) {
for (xi in -1..+2) {
if (xi !in 0..1) {
val tileHere = world.getTileFromTerrain(x + xi, y - growCnt)
if (BlockCodex[tileHere].hasTag("TREETRUNK"))
world.setTileTerrain(x + xi, y - growCnt, Block.AIR, true)
}
else {
world.setTileTerrain(x + xi, y - growCnt, trunk, true)
}
else throw IllegalArgumentException("Unknown tree size: $size")
return true
}
private fun drawBulb(world: GameWorld, x: Int, y: Int, width: Int, height: Int, foliage: ItemID, growCnt0: Int): Int {
var growCnt = growCnt0
val xStart = x - width / 2 + (1 - (width % 2))
val xEnd = xStart + width
var xStart2 = xStart
var xEnd2 = xEnd
val r = (XXHash32.hashGeoCoord(x, y) * width * height + growCnt).and(0xffffff) / 16777216f
r.let {
if (it < 0.25) xStart2 += 1
else if (it < 0.5) xEnd2 -= 1
}
val xs1 = xStart until xEnd
val xs2 = xStart2 until xEnd2
for (i in 0 until height) {
for (x in if (i == height - 1 && i > 0) xs2 else xs1) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
}
// bulb base
for (x in x-2..x+3) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
for (x in x-3..x+4) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
// bulb 1
growCnt = drawBulb(x, y, 10, bulb1, foliage, growCnt)
// bulb 2
growCnt = drawBulb(x, y, 8, bulb2, foliage, growCnt)
// bulb 3
growCnt = drawBulb(x, y, 6, bulb3, foliage, growCnt)
// bulb 4
growCnt = drawBulb(x, y, 4, bulb4, foliage, growCnt)
return growCnt
}
else throw IllegalArgumentException("Unknown tree size: $size")
}
private fun drawBulb(x: Int, y: Int, width: Int, height: Int, foliage: ItemID, growCnt0: Int): Int {
var growCnt = growCnt0
val xStart = x - width / 2 + (1 - (width % 2))
val xEnd = xStart + width
var xStart2 = xStart
var xEnd2 = xEnd
/**
* @return normally distributed integer, for `maxvar=1`, `[-1, 0, 1]`; for `maxvar=2`, `[-2, -1, 0, 1, 2]`, etc.
*/
private fun fudgeN(x: Int, y: Int, vararg hs: Int) = hs.sumOf { (nextDouble(x, y, it) * 3).toInt() - 1 }
val r = (XXHash32.hashGeoCoord(x, y) * width * height + growCnt).and(0xffffff) / 16777216f
r.let {
if (it < 0.25) xStart2 += 1
else if (it < 0.5) xEnd2 -= 1
private fun nextDouble(x: Int, y: Int, h: Int): Double {
return ((XXHash32.hashGeoCoord(x, y) * 31 + h) and 0xFFFFFF) / 16777216.0
}
val xs1 = xStart until xEnd
val xs2 = xStart2 until xEnd2
for (i in 0 until height) {
for (x in if (i == height - 1 && i > 0) xs2 else xs1) {
val tileHere = world.getTileFromTerrain(x, y - growCnt)
if (BlockCodex[tileHere].hasTag("INCONSEQUENTIAL"))
world.setTileTerrain(x, y - growCnt, foliage, true)
}
growCnt += 1
}
return growCnt
}
/**
@@ -418,11 +427,7 @@ class Treegen(world: GameWorld, isFinal: Boolean, seed: Long, val terragenParams
return r
}
/**
* @return normally distributed integer, for `maxvar=1`, `[-1, 0, 1]`; for `maxvar=2`, `[-2, -1, 0, 1, 2]`, etc.
*/
private fun fudgeN(x: Int, y: Int, vararg hs: Int) = hs.sumOf { (nextDouble(x, y, it) * 3).toInt() - 1 }
}
data class TreegenParams(

Binary file not shown.