diff --git a/internal/asset/texture/world/planks_oak.png b/internal/asset/texture/world/planks_oak.png new file mode 100644 index 0000000..5de3861 Binary files /dev/null and b/internal/asset/texture/world/planks_oak.png differ diff --git a/internal/asset/texture/world/water.png b/internal/asset/texture/world/water.png new file mode 100644 index 0000000..9cce028 Binary files /dev/null and b/internal/asset/texture/world/water.png differ diff --git a/internal/game/logic.go b/internal/game/logic.go index fb0a998..db60f8d 100644 --- a/internal/game/logic.go +++ b/internal/game/logic.go @@ -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} }) diff --git a/internal/util/itype/vec.go b/internal/util/itype/vec.go index 043e957..0948ab0 100644 --- a/internal/util/itype/vec.go +++ b/internal/util/itype/vec.go @@ -18,9 +18,13 @@ type Vec3i [3]int func (v Vec3i) ToFloat32() Vec3f { return Vec3f{float32(v[0]), float32(v[1]), float32(v[2])} } func (v Vec3i) ToFloat64() Vec3d { return Vec3d{float64(v[0]), float64(v[1]), float64(v[2])} } -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) 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 diff --git a/internal/world/block.go b/internal/world/block.go index 1d52c69..b480bb9 100644 --- a/internal/world/block.go +++ b/internal/world/block.go @@ -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) } diff --git a/internal/world/blocks/default.go b/internal/world/blocks/default.go new file mode 100644 index 0000000..baff876 --- /dev/null +++ b/internal/world/blocks/default.go @@ -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() +} diff --git a/internal/world/blocks/helper_appendface.go b/internal/world/blocks/helper_appendface.go new file mode 100644 index 0000000..157ff47 --- /dev/null +++ b/internal/world/blocks/helper_appendface.go @@ -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 +} diff --git a/internal/world/blocks/water.go b/internal/world/blocks/water.go new file mode 100644 index 0000000..b9871ef --- /dev/null +++ b/internal/world/blocks/water.go @@ -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 +} diff --git a/internal/world/chunk.go b/internal/world/chunk.go index 97c2522..4b3acff 100644 --- a/internal/world/chunk.go +++ b/internal/world/chunk.go @@ -21,7 +21,13 @@ type Chunk struct { renderChanged bool vao, vbo uint32 vbolen int - vertUpdate chan []Vertex + 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 } diff --git a/internal/world/default_blocks.go b/internal/world/default_blocks.go deleted file mode 100644 index 6d2a10c..0000000 --- a/internal/world/default_blocks.go +++ /dev/null @@ -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() -} diff --git a/internal/world/render.go b/internal/world/render.go index 06c8cc6..227beff 100644 --- a/internal/world/render.go +++ b/internal/world/render.go @@ -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, diff --git a/internal/world/world.go b/internal/world/world.go index f902d02..ad5fdc5 100644 --- a/internal/world/world.go +++ b/internal/world/world.go @@ -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{} diff --git a/internal/world/worldgen/worldgen.go b/internal/world/worldgen/worldgen.go index 6c62767..8699d81 100644 --- a/internal/world/worldgen/worldgen.go +++ b/internal/world/worldgen/worldgen.go @@ -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 {