diff --git a/cmd/mtseeder/baselevel.go b/cmd/mtseeder/baselevel.go index cbd8ebf..7c4c839 100644 --- a/cmd/mtseeder/baselevel.go +++ b/cmd/mtseeder/baselevel.go @@ -68,7 +68,7 @@ func createBaseLevel( btc := common.NewBaseTileCreator( client, colors, bg, int16(yMin), int16(yMax), - transparent, baseDir, false) + transparent, baseDir, nil) go createTiles(btc, jobs, &done) } diff --git a/cmd/mtwebmapper/tilesupdater.go b/cmd/mtwebmapper/tilesupdater.go index 5cd8cc1..4d360e0 100644 --- a/cmd/mtwebmapper/tilesupdater.go +++ b/cmd/mtwebmapper/tilesupdater.go @@ -177,6 +177,8 @@ func activeChanges(changes []xzc) map[xz]bool { func (tu *tileUpdater) doUpdates() { + bth := common.NewBaseTileHash() + for { tu.cond.L.Lock() for len(tu.changes) == 0 { @@ -201,7 +203,7 @@ func (tu *tileUpdater) doUpdates() { btc := common.NewBaseTileCreator( client, tu.colors, tu.bg, tu.yMin, tu.yMax, - tu.transparent, baseDir, true) + tu.transparent, baseDir, bth.Update) done.Add(1) go tu.updateBaseTiles(jobs, btc, &done) } @@ -334,8 +336,12 @@ func (tu *tileUpdater) updateBaseTiles( for job := range jobs { xz := job.dequantize() //log.Printf("%d/%d %d/%d", x, z, job.X, job.Z) - if err := btc.CreateTile(xz.X-1, xz.Z-1, int(job.X), int(job.Z)); err != nil { + updated, err := btc.CreateTile(xz.X-1, xz.Z-1, int(job.X), int(job.Z)) + if err != nil { log.Printf("WARN: create tile failed: %s\n", err) } + if !updated { + job.canceled = true + } } } diff --git a/common/basetilecreator.go b/common/basetilecreator.go index 35ea2f5..1b290f5 100644 --- a/common/basetilecreator.go +++ b/common/basetilecreator.go @@ -5,6 +5,7 @@ package common import ( + "image" "image/color" "io/ioutil" "log" @@ -49,6 +50,8 @@ var tileDepths = [...][2]int16{ var BackgroundColor = color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff} +type BaseTileUpdateFunc func(x, y int, img image.Image) bool + type BaseTileCreator struct { client *RedisClient colors *Colors @@ -57,7 +60,7 @@ type BaseTileCreator struct { yMin int16 yMax int16 baseDir string - update bool + update BaseTileUpdateFunc emptyImage []byte bg color.RGBA } @@ -69,7 +72,7 @@ func NewBaseTileCreator( yMin, yMax int16, transparent bool, baseDir string, - update bool) *BaseTileCreator { + update BaseTileUpdateFunc) *BaseTileCreator { renderer := NewRenderer(tileWidth, tileHeight, transparent) yMin, yMax = Order16(yMin, yMax) return &BaseTileCreator{ @@ -88,7 +91,7 @@ func (btc *BaseTileCreator) Close() error { return btc.client.Close() } -func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) error { +func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) (bool, error) { btc.renderer.Reset() btc.renderer.SetPos(x, z) btc.yOrder.Reset() @@ -128,7 +131,7 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) error { c2.Z = area.Z2 + z query := Cuboid{P1: c1, P2: c2} if err := btc.client.QueryCuboid(query, drawBlock); err != nil { - return err + return false, err } if err := btc.yOrder.Drain(btc.colors); err != nil { log.Printf("WARN: rendering block failed: %s\n", err) @@ -140,28 +143,34 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) error { path := filepath.Join(btc.baseDir, strconv.Itoa(i), strconv.Itoa(j)+".png") // Empty images are likely to be produced during seeding. - if !btc.update && btc.renderer.IsEmpty() { + if btc.update == nil && btc.renderer.IsEmpty() { // To avoid redundant encoding cache the resulting empty image. if btc.emptyImage == nil { var err error m := BackgroundImage((tileWidth-2)*16, (tileHeight-2)*16, btc.bg) if btc.emptyImage, err = EncodeToMem(m); err != nil { - return err + return false, err } } //log.Printf("Writing empty (%d, %d) to file %s\n", x, z, path) - return ioutil.WriteFile(path, btc.emptyImage, 0666) + return true, ioutil.WriteFile(path, btc.emptyImage, 0666) } image := btc.renderer.CreateShadedImage( 16, 16, (tileWidth-2)*16, (tileHeight-2)*16, btc.colors, btc.bg) - log.Printf("Writing (%d, %d) to file %s\n", x, z, path) - - if !btc.update { - return SaveAsPNG(path, image) + if btc.update == nil { + log.Printf("Writing (%d, %d) to file %s.\n", x, z, path) + return true, SaveAsPNG(path, image) } - return SaveAsPNGAtomic(path, image) + if btc.update(i, j, image) { + log.Printf("Writing (%d, %d) to file %s.\n", x, z, path) + return true, SaveAsPNGAtomic(path, image) + } + + log.Printf("File %s does not change.\n", path) + + return false, nil }