worldgen water, fixes

This commit is contained in:
Edgaru089 2022-01-28 15:24:03 +08:00
parent 7b6c16789c
commit 904221ac14
13 changed files with 245 additions and 72 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 411 B

View File

@ -47,8 +47,8 @@ func (g *Game) Init(win *glfw.Window) {
var seed int64 = time.Now().Unix()
gensync := make(chan struct{})
gensynccnt := 0
for i := -4; i <= 4; i++ {
for j := -4; j <= 4; j++ {
for i := -8; i <= 8; i++ {
for j := -8; j <= 8; j++ {
c := &world.Chunk{}
g.world.SetChunk(i, j, c)
go func() {
@ -68,7 +68,7 @@ func (g *Game) Init(win *glfw.Window) {
io.DisplaySize[0], io.DisplaySize[1] = win.GetFramebufferSize()
win.SetSizeCallback(func(w *glfw.Window, width, height int) {
win.SetCursorPos(float64(width)/2, float64(height)/2)
//win.SetCursorPos(float64(width)/2, float64(height)/2)
g.view.Aspect(float32(width) / float32(height))
io.DisplaySize = itype.Vec2i{width, height}
})

View File

@ -21,6 +21,10 @@ func (v Vec3i) ToFloat64() Vec3d { return Vec3d{float64(v[0]), float64(v[1]), fl
func (v Vec3i) Add(add Vec3i) Vec3i { return Vec3i{v[0] + add[0], v[1] + add[1], v[2] + add[2]} }
func (v Vec3i) Addv(x, y, z int) Vec3i { return Vec3i{v[0] + x, v[1] + y, v[2] + z} }
func (v Vec3i) MultiplyInt(mult int) Vec3i { return Vec3i{v[0] * mult, v[1] * mult, v[2] * mult} }
func (v Vec3i) Multiplyv(x, y, z int) Vec3i { return Vec3i{v[0] * x, v[1] * y, v[2] * z} }
func (v Vec3i) Multiply(mult Vec3i) Vec3i {
return Vec3i{v[0] * mult[0], v[1] * mult[1], v[2] * mult[2]}
}
// Vec4i is a four-element int vector
type Vec4i [4]int

View File

@ -34,6 +34,7 @@ type BlockAppearance struct {
position itype.Vec3i,
aux int,
data itype.Dataset,
world *World,
vertexArray []Vertex,
) []Vertex
}
@ -59,7 +60,7 @@ type BlockBehaviour interface {
// with Minor ID aux, and Dataset data.
//
// If RequireDataset if false, data is nil.
Appearance(position itype.Vec3i, aux int, data itype.Dataset) BlockAppearance
Appearance(position itype.Vec3i, aux int, data itype.Dataset, world *World) BlockAppearance
// BlockUpdate is called when RequireBlockUpdate is true and the block at
// global position Position, with Minor ID aux, and Dataset data has a neighbor
@ -68,7 +69,7 @@ type BlockBehaviour interface {
// If RequireDataset if false, data is nil.
//
// Return true if this block also changed state, false otherwise.
BlockUpdate(position itype.Vec3i, aux int, data itype.Dataset) bool
BlockUpdate(position itype.Vec3i, aux int, data itype.Dataset, world *World) bool
}
type blockBehaviourStatic struct {
@ -78,10 +79,10 @@ type blockBehaviourStatic struct {
func (blockBehaviourStatic) Static() bool { return true }
func (blockBehaviourStatic) RequireDataset() bool { return false }
func (blockBehaviourStatic) RequireBlockUpdate() bool { return false }
func (b blockBehaviourStatic) Appearance(position itype.Vec3i, aux int, data itype.Dataset) BlockAppearance {
func (b blockBehaviourStatic) Appearance(position itype.Vec3i, aux int, data itype.Dataset, world *World) BlockAppearance {
return b.app
}
func (blockBehaviourStatic) BlockUpdate(position itype.Vec3i, aux int, data itype.Dataset) bool {
func (blockBehaviourStatic) BlockUpdate(position itype.Vec3i, aux int, data itype.Dataset, world *World) bool {
return false
}
@ -112,7 +113,7 @@ func RegisterBlockBehaviour(id int, b BlockBehaviour) bool {
func DoneRegisteringBlockBehaviour() {
for id, b := range behaviour {
if b.Static() {
appearance[id] = b.Appearance(itype.Vec3i{}, 0, nil)
appearance[id] = b.Appearance(itype.Vec3i{}, 0, nil, nil)
}
}
@ -120,7 +121,7 @@ func DoneRegisteringBlockBehaviour() {
}
// GetBlockAppearance gets the block appearance of the given block in the fastest way possible.
func GetBlockAppearance(position itype.Vec3i, id, aux int, data itype.Dataset) BlockAppearance {
func GetBlockAppearance(position itype.Vec3i, id, aux int, data itype.Dataset, world *World) BlockAppearance {
if app, ok := appearance[id]; ok { // Cache
if app.Hitbox == (itype.Boxd{}) {
app.Hitbox = itype.Boxd{
@ -137,7 +138,7 @@ func GetBlockAppearance(position itype.Vec3i, id, aux int, data itype.Dataset) B
panic(fmt.Sprint("invalid block type ", id))
}
app := b.Appearance(position, aux, data)
app := b.Appearance(position, aux, data, world)
if app.Hitbox == (itype.Boxd{}) {
app.Hitbox = itype.Boxd{
OffX: 0, OffY: 0, OffZ: 0,
@ -157,12 +158,13 @@ type Block struct {
Id, Aux int
Dataset itype.Dataset
Behaviour BlockBehaviour
World *World
}
// Appearance is a shortcut for Behaviour.Appearance().
// It returns the Appearance of the block with the given parameters.
func (b *Block) Appearance(position itype.Vec3i) BlockAppearance {
return b.Behaviour.Appearance(position, b.Aux, b.Dataset)
func (b Block) Appearance(position itype.Vec3i) BlockAppearance {
return b.Behaviour.Appearance(position, b.Aux, b.Dataset, b.World)
}
// BlockUpdate is a shortcut for Behaviour.BlockUpdate().
@ -173,6 +175,6 @@ func (b *Block) Appearance(position itype.Vec3i) BlockAppearance {
// If RequireDataset if false, data is nil.
//
// Return true if this block also changed state, false otherwise.
func (b *Block) BlockUpdate(position itype.Vec3i) bool {
return b.Behaviour.BlockUpdate(position, b.Aux, b.Dataset)
func (b Block) BlockUpdate(position itype.Vec3i) bool {
return b.Behaviour.BlockUpdate(position, b.Aux, b.Dataset, b.World)
}

View File

@ -0,0 +1,49 @@
package blocks
import "edgaru089.ml/go/gl01/internal/world"
const (
Nil = iota
Debug
DebugDir
DebugNonexist
Stone
Dirt
Grass
Bedrock
Sand
LogOak
LeavesOak
PlanksOak
Water
Count
)
func init() {
world.RegisterBlockBehaviour(1, world.BlockBehaviourStatic(world.BlockAppearance{Name: "debug"}))
world.RegisterBlockBehaviour(2, world.BlockBehaviourStatic(world.BlockAppearance{Name: "debug_dir", RenderType: world.SixTexture}))
world.RegisterBlockBehaviour(3, world.BlockBehaviourStatic(world.BlockAppearance{Name: "debug_nonexist"}))
world.RegisterBlockBehaviour(4, world.BlockBehaviourStatic(world.BlockAppearance{Name: "stone"}))
world.RegisterBlockBehaviour(5, world.BlockBehaviourStatic(world.BlockAppearance{Name: "dirt"}))
world.RegisterBlockBehaviour(6, world.BlockBehaviourStatic(world.BlockAppearance{Name: "grass", RenderType: world.ThreeTexture}))
world.RegisterBlockBehaviour(7, world.BlockBehaviourStatic(world.BlockAppearance{Name: "bedrock"}))
world.RegisterBlockBehaviour(8, world.BlockBehaviourStatic(world.BlockAppearance{Name: "sand"}))
world.RegisterBlockBehaviour(9, world.BlockBehaviourStatic(world.BlockAppearance{Name: "log_oak", RenderType: world.ThreeTexture}))
world.RegisterBlockBehaviour(10, world.BlockBehaviourStatic(world.BlockAppearance{Name: "leaves_oak"}))
world.RegisterBlockBehaviour(11, world.BlockBehaviourStatic(world.BlockAppearance{Name: "planks_oak"}))
world.RegisterBlockBehaviour(12, WaterBehaviour{})
if Count != 13 {
panic("world.DefaultBlocks: block count not correct (check for block numbering in default_blocks.go)")
}
world.DoneRegisteringBlockBehaviour()
}

View File

@ -0,0 +1,78 @@
package blocks
import (
"edgaru089.ml/go/gl01/internal/asset"
"edgaru089.ml/go/gl01/internal/util/itype"
"edgaru089.ml/go/gl01/internal/world"
)
// texname is the full filename of the texture file (with .png)
// faceOffset is added to each vertex
func appendFace(face itype.Direction, pos itype.Vec3i, texname string, faceOffset itype.Vec3f, arr []world.Vertex) []world.Vertex {
switch face {
case itype.XPlus: // X+
arr = append(arr,
// Vertex Position Normal Vector(normalized) Texture Coord Light
world.Vertex{pos.Addv(1, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{1, 1}, 16},
world.Vertex{pos.Addv(1, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{1, 0}, 16},
world.Vertex{pos.Addv(1, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(1, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{1, 1}, 16},
world.Vertex{pos.Addv(1, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(1, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{1, 0, 0}, itype.Vec2f{0, 1}, 16},
)
case itype.XMinus: // X-
arr = append(arr,
world.Vertex{pos.Addv(0, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{0, 1}, 16},
world.Vertex{pos.Addv(0, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{1, 0}, 16},
world.Vertex{pos.Addv(0, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(0, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{0, 1}, 16},
world.Vertex{pos.Addv(0, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{1, 1}, 16},
world.Vertex{pos.Addv(0, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{-1, 0, 0}, itype.Vec2f{1, 0}, 16},
)
case itype.YPlus: // Y+
arr = append(arr,
world.Vertex{pos.Addv(0, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(0, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{0, 1}, 16},
world.Vertex{pos.Addv(1, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{1, 0}, 16},
world.Vertex{pos.Addv(0, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{0, 1}, 16},
world.Vertex{pos.Addv(1, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{1, 1}, 16},
world.Vertex{pos.Addv(1, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 1, 0}, itype.Vec2f{1, 0}, 16},
)
case itype.YMinus: // Y-
arr = append(arr,
world.Vertex{pos.Addv(0, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{1, 0}, 16},
world.Vertex{pos.Addv(1, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(1, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{0, 1}, 16},
world.Vertex{pos.Addv(0, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{1, 0}, 16},
world.Vertex{pos.Addv(1, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{0, 1}, 16},
world.Vertex{pos.Addv(0, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, -1, 0}, itype.Vec2f{1, 1}, 16},
)
case itype.ZPlus: // Z+
arr = append(arr,
world.Vertex{pos.Addv(0, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{0, 1}, 16},
world.Vertex{pos.Addv(1, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{1, 1}, 16},
world.Vertex{pos.Addv(0, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(1, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{1, 0}, 16},
world.Vertex{pos.Addv(0, 1, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(1, 0, 1).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, 1}, itype.Vec2f{1, 1}, 16},
)
case itype.ZMinus: // Z-
arr = append(arr,
world.Vertex{pos.Addv(0, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{1, 1}, 16},
world.Vertex{pos.Addv(0, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{1, 0}, 16},
world.Vertex{pos.Addv(1, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(0, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{1, 1}, 16},
world.Vertex{pos.Addv(1, 1, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{0, 0}, 16},
world.Vertex{pos.Addv(1, 0, 0).ToFloat32().Add(faceOffset), itype.Vec3f{0, 0, -1}, itype.Vec2f{0, 1}, 16},
)
}
texrect := asset.WorldTextureAtlas.RectNormalized(texname)
for i := len(arr) - 6; i < len(arr); i++ {
arr[i].Texture[0] = texrect.Left + arr[i].Texture[0]*texrect.Width
arr[i].Texture[1] = texrect.Top + arr[i].Texture[1]*texrect.Height
}
return arr
}

View File

@ -0,0 +1,37 @@
package blocks
import (
"edgaru089.ml/go/gl01/internal/util/itype"
"edgaru089.ml/go/gl01/internal/world"
)
type WaterBehaviour struct{}
func (WaterBehaviour) Static() bool { return false }
func (WaterBehaviour) RequireDataset() bool { return false }
func (WaterBehaviour) RequireBlockUpdate() bool { return false }
func (b WaterBehaviour) Appearance(position itype.Vec3i, aux int, data itype.Dataset, w *world.World) world.BlockAppearance {
return world.BlockAppearance{
Name: "water",
Transparent: true,
NotSolid: true,
RenderType: world.CustomRendering,
CustomRenderAppend: func(
position itype.Vec3i,
aux int,
data itype.Dataset,
w *world.World,
vertexArray []world.Vertex) []world.Vertex {
if block := w.Block(position.Addv(0, 1, 0)); block.Id != Water {
return appendFace(itype.YPlus, position, "water.png", itype.Vec3f{0, -0.125, 0}, vertexArray)
}
return vertexArray
},
}
}
func (WaterBehaviour) BlockUpdate(position itype.Vec3i, aux int, data itype.Dataset, w *world.World) bool {
return false
}

View File

@ -21,7 +21,13 @@ type Chunk struct {
renderChanged bool
vao, vbo uint32
vbolen int
water struct {
vao, vbo uint32
vbolen int
}
vertUpdate chan []Vertex
world *World
}
func (c *Chunk) SetChunkID(x, z int) {
@ -30,8 +36,9 @@ func (c *Chunk) SetChunkID(x, z int) {
c.renderChanged = true
}
func (c *Chunk) SetBlock(x, y, z int, id int) {
func (c *Chunk) SetBlock(x, y, z int, id, aux int) {
c.Id[x][y][z] = uint16(id)
c.Aux[x][y][z] = uint16(aux)
c.renderChanged = true
}

View File

@ -1,40 +0,0 @@
package world
const (
BlockNil = iota
BlockDebug
BlockDebugDir
BlockDebugNonexist
BlockStone
BlockDirt
BlockGrass
BlockBedrock
BlockSand
BlockLogOak
BlockLeavesOak
BlockCount
)
func init() {
RegisterBlockBehaviour(1, BlockBehaviourStatic(BlockAppearance{Name: "debug"}))
RegisterBlockBehaviour(2, BlockBehaviourStatic(BlockAppearance{Name: "debug_dir", RenderType: SixTexture}))
RegisterBlockBehaviour(3, BlockBehaviourStatic(BlockAppearance{Name: "debug_nonexist"}))
RegisterBlockBehaviour(4, BlockBehaviourStatic(BlockAppearance{Name: "stone"}))
RegisterBlockBehaviour(5, BlockBehaviourStatic(BlockAppearance{Name: "dirt"}))
RegisterBlockBehaviour(6, BlockBehaviourStatic(BlockAppearance{Name: "grass", RenderType: ThreeTexture}))
RegisterBlockBehaviour(7, BlockBehaviourStatic(BlockAppearance{Name: "bedrock"}))
RegisterBlockBehaviour(8, BlockBehaviourStatic(BlockAppearance{Name: "sand"}))
RegisterBlockBehaviour(9, BlockBehaviourStatic(BlockAppearance{Name: "log_oak", RenderType: ThreeTexture}))
RegisterBlockBehaviour(10, BlockBehaviourStatic(BlockAppearance{Name: "leaves_oak"}))
if BlockCount != 11 {
panic("world.DefaultBlocks: block count not correct (check for block numbering in default_blocks.go)")
}
DoneRegisteringBlockBehaviour()
}

View File

@ -34,7 +34,7 @@ func (c *Chunk) InitRender() {
gl.EnableVertexAttribArray(2)
gl.EnableVertexAttribArray(3)
c.vertUpdate = make(chan []Vertex)
c.vertUpdate = make(chan []Vertex, 2)
c.renderChanged = true
}
@ -127,7 +127,7 @@ func (c *Chunk) AppendVertex(arr []Vertex) []Vertex {
continue
}
app := GetBlockAppearance(off.Addv(i, j, k), int(c.Id[i][j][k]), int(c.Aux[i][j][k]), nil)
app := GetBlockAppearance(off.Addv(i, j, k), int(c.Id[i][j][k]), int(c.Aux[i][j][k]), nil, c.world)
switch app.RenderType {
case OneTexture:
arr = c.appendFace(itype.XPlus, itype.Vec3i{i, j, k}, app.Name+".png", arr)
@ -151,7 +151,7 @@ func (c *Chunk) AppendVertex(arr []Vertex) []Vertex {
arr = c.appendFace(itype.ZPlus, itype.Vec3i{i, j, k}, app.Name+"_z+.png", arr)
arr = c.appendFace(itype.ZMinus, itype.Vec3i{i, j, k}, app.Name+"_z-.png", arr)
case CustomRendering:
arr = app.CustomRenderAppend(off.Addv(i, j, k), int(c.Aux[i][j][k]), nil, arr)
arr = app.CustomRenderAppend(off.Addv(i, j, k), int(c.Aux[i][j][k]), nil, c.world, arr)
}
}
@ -174,11 +174,16 @@ func (c *Chunk) appendFace(face itype.Direction, pos itype.Vec3i, texname string
next.Addv(c.X*ChunkSizeX, 0, c.Z*ChunkSizeZ),
int(c.Id[next[0]][next[1]][next[2]]),
int(c.Aux[next[0]][next[1]][next[2]]),
nil,
nil, c.world,
).Transparent { // face next to a solid block
return arr // skip!
}
worldnext := pos.Add(itype.DirectionVeci[face]).Addv(c.X*ChunkSizeX, 0, c.Z*ChunkSizeZ)
if block := c.world.Block(worldnext); block.Id != 0 && !block.Appearance(worldnext).Transparent {
return arr // skip!
}
switch face {
case itype.XPlus: // X+
arr = append(arr,

View File

@ -42,6 +42,7 @@ func (w *World) SetChunk(x, z int, c *Chunk) {
c.X = x
c.Z = z
c.renderChanged = true
c.world = w
w.Chunks[itype.Vec2i{x, z}] = c
c.InitRender()
}
@ -99,6 +100,26 @@ func (w *World) Block(pos itype.Vec3i) Block {
}
}
// SetBlock sets the block at the given position, returning its Block.
//
// It fails if the chunk is not loaded, and an empty Block{} is returned.
func (w *World) SetBlock(pos itype.Vec3i, id, aux int, dataset itype.Dataset) Block {
cx, cz := BlockPosToChunk(pos)
cix, ciy, ciz := BlockPosToInChunk(pos)
c, ok := w.Chunks[itype.Vec2i{cx, cz}]
if !ok || ciy < 0 || ciy >= ChunkSizeY {
return Block{}
}
c.SetBlock(cix, ciy, ciz, id, aux)
return Block{
Id: int(c.Id[cix][ciy][ciz]),
Aux: int(c.Aux[cix][ciy][ciz]),
Dataset: nil,
Behaviour: GetBlockBehaviour(int(c.Id[cix][ciy][ciz])),
}
}
// LoadChunkFromGob loads (or overwrites) chunk [id.x, id.z] from the Gob-encoding file.
func (w *World) LoadChunkFromGob(id itype.Vec2i, file io.Reader) (err error) {
c := &Chunk{}

View File

@ -4,6 +4,7 @@ import (
"sync"
packworld "edgaru089.ml/go/gl01/internal/world"
"edgaru089.ml/go/gl01/internal/world/blocks"
"github.com/aquilax/go-perlin"
)
@ -15,8 +16,8 @@ const (
AltitudeDensity = 10 // Density of the noise in altitude
Sealevel = 63 // Space with Y=63 and lower should be the sea
Highest = 72 // Highest part of the terrain
Lowest = 56 // Lowest part of the terrain
Highest = 84 // Highest part of the terrain
Lowest = 60 // Lowest part of the terrain
)
var perlins map[int64]*perlin.Perlin
@ -54,21 +55,30 @@ func Chunk(chunk *packworld.Chunk, world *packworld.World, seed int64) {
float64(offZ+z)/AltitudeDensity))
//log.Printf("height = %d (noise=%.5f)", height, p.Noise2D(float64(offX+x), float64(offZ+z)))
// water
for y := Sealevel; y > height; y-- {
chunk.Id[x][y][z] = blocks.Water
}
// covering dirt
chunk.Id[x][height][z] = packworld.BlockGrass
//chunk.Id[x][height][z] = packworld.BlockDebugDir
chunk.Id[x][height-1][z] = packworld.BlockDirt
chunk.Id[x][height-2][z] = packworld.BlockDirt
chunk.Id[x][height-3][z] = packworld.BlockDirt
if height >= Sealevel {
chunk.Id[x][height][z] = blocks.Grass
} else {
chunk.Id[x][height][z] = blocks.Dirt
}
//chunk.Id[x][height][z] = blocks.DebugDir
chunk.Id[x][height-1][z] = blocks.Dirt
chunk.Id[x][height-2][z] = blocks.Dirt
chunk.Id[x][height-3][z] = blocks.Dirt
height -= 4
// stone in the middle
for y := height; y >= 1; y-- {
chunk.Id[x][y][z] = packworld.BlockStone
chunk.Id[x][y][z] = blocks.Stone
}
// bedrock at the bottom
chunk.Id[x][0][z] = packworld.BlockBedrock
chunk.Id[x][0][z] = blocks.Bedrock
// plant trees
if height >= 50 && height <= 70 {