package world import ( "image" "image/color" "github.com/bedrock-tool/bedrocktool/utils" "github.com/df-mc/dragonfly/server/block" "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/world" "github.com/df-mc/dragonfly/server/world/chunk" ) func isBlockLightblocking(b world.Block) bool { d, isDiffuser := b.(block.LightDiffuser) _, isSlab := b.(block.Slab) noDiffuse := isDiffuser && d.LightDiffusionLevel() == 0 return noDiffuse && !isSlab } func blockColorAt(c *chunk.Chunk, x uint8, y int16, z uint8) (blockColor color.RGBA) { if y <= int16(c.Range().Min()) { return color.RGBA{0, 0, 0, 0} } blockColor = color.RGBA{255, 0, 255, 255} rid := c.Block(x, y, z, 0) if rid == 0 && y == int16(c.Range().Min()) { // void blockColor = color.RGBA{0, 0, 0, 255} } else { b, found := world.BlockByRuntimeID(rid) if found { if isBlockLightblocking(b) { return blockColorAt(c, x, y-1, z) } _, isWater := b.(block.Water) if !isWater { return b.Color() } // get the first non water block at the position heightBlock := c.HeightMap().At(x, z) depth := y - heightBlock if depth > 0 { blockColor = blockColorAt(c, x, heightBlock, z) } // blend that blocks color with water depending on depth waterColor := (&block.Water{}).Color() waterColor.A = uint8(utils.Clamp(int(150+depth*7), 255)) blockColor = utils.BlendColors(blockColor, waterColor) blockColor.R -= uint8(depth * 2) blockColor.G -= uint8(depth * 2) blockColor.B -= uint8(depth * 2) } /* if blockColor.R == 0 || blockColor.R == 255 && blockColor.B == 255 { name, nbt := b.EncodeBlock() fmt.Printf("unknown color %d %s %s %s\n", rid, reflect.TypeOf(b), name, nbt) b.Color() } */ } return blockColor } func chunkGetColorAt(c *chunk.Chunk, x uint8, y int16, z uint8) color.RGBA { haveUp := false cube.Pos{int(x), int(y), int(z)}. Side(cube.FaceUp). Neighbours(func(neighbour cube.Pos) { if neighbour.X() < 0 || neighbour.X() >= 16 || neighbour.Z() < 0 || neighbour.Z() >= 16 || neighbour.Y() > c.Range().Max() || haveUp { return } blockRid := c.Block(uint8(neighbour[0]), int16(neighbour[1]), uint8(neighbour[2]), 0) if blockRid > 0 { b, found := world.BlockByRuntimeID(blockRid) if found { if isBlockLightblocking(b) { haveUp = true } } } }, cube.Range{int(y + 1), int(y + 1)}) blockColor := blockColorAt(c, x, y, z) if haveUp { if blockColor.R > 10 { blockColor.R -= 10 } if blockColor.G > 10 { blockColor.G -= 10 } if blockColor.B > 10 { blockColor.B -= 10 } } return blockColor } func Chunk2Img(c *chunk.Chunk) *image.RGBA { img := image.NewRGBA(image.Rect(0, 0, 16, 16)) hm := c.HeightMapWithWater() for x := uint8(0); x < 16; x++ { for z := uint8(0); z < 16; z++ { img.SetRGBA( int(x), int(z), chunkGetColorAt(c, x, hm.At(x, z), z), ) } } return img }