package app import ( "encoding/json" "net/http" "strconv" "time" "go.etcd.io/bbolt" ) func (a *App) wipeTile(rw http.ResponseWriter, req *http.Request) { if a.requireAdmin(rw, req) == nil { return } mraw := req.FormValue("map") mapid, err := strconv.Atoi(mraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } xraw := req.FormValue("x") x, err := strconv.Atoi(xraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } yraw := req.FormValue("y") y, err := strconv.Atoi(yraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } c := Coord{ X: x, Y: y, } a.db.Update(func(tx *bbolt.Tx) error { grids := tx.Bucket([]byte("grids")) if grids == nil { return nil } ids := [][]byte{} err := grids.ForEach(func(k, v []byte) error { g := GridData{} err := json.Unmarshal(v, &g) if err != nil { return err } if g.Coord == c && g.Map == mapid { ids = append(ids, k) } return nil }) if err != nil { return err } for _, id := range ids { grids.Delete(id) } return nil }) a.SaveTile(mapid, c, 0, "", -1) for z := 1; z <= 5; z++ { c = c.Parent() a.updateZoomLevel(mapid, c, z) } rw.WriteHeader(200) } func (a *App) setCoords(rw http.ResponseWriter, req *http.Request) { if a.requireAdmin(rw, req) == nil { return } mraw := req.FormValue("map") mapid, err := strconv.Atoi(mraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } fxraw := req.FormValue("fx") fx, err := strconv.Atoi(fxraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } fyraw := req.FormValue("fy") fy, err := strconv.Atoi(fyraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } fc := Coord{ X: fx, Y: fy, } txraw := req.FormValue("tx") tx, err := strconv.Atoi(txraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } tyraw := req.FormValue("ty") ty, err := strconv.Atoi(tyraw) if err != nil { http.Error(rw, "coord parse failed", http.StatusBadRequest) return } tc := Coord{ X: tx, Y: ty, } diff := Coord{ X: tc.X - fc.X, Y: tc.Y - fc.Y, } tds := []*TileData{} a.db.Update(func(tx *bbolt.Tx) error { grids := tx.Bucket([]byte("grids")) if grids == nil { return nil } tiles := tx.Bucket([]byte("tiles")) if tiles == nil { return nil } mapZooms := tiles.Bucket([]byte(strconv.Itoa(mapid))) if mapZooms == nil { return nil } mapTiles := mapZooms.Bucket([]byte("0")) err := grids.ForEach(func(k, v []byte) error { g := GridData{} err := json.Unmarshal(v, &g) if err != nil { return err } if g.Map == mapid { g.Coord.X += diff.X g.Coord.Y += diff.Y raw, _ := json.Marshal(g) grids.Put(k, raw) } return nil }) if err != nil { return err } err = mapTiles.ForEach(func(k, v []byte) error { td := &TileData{} err := json.Unmarshal(v, &td) if err != nil { return err } td.Coord.X += diff.X td.Coord.Y += diff.Y tds = append(tds, td) return nil }) if err != nil { return err } err = tiles.DeleteBucket([]byte(strconv.Itoa(mapid))) if err != nil { return err } return nil }) needProcess := map[zoomproc]struct{}{} for _, td := range tds { a.SaveTile(td.MapID, td.Coord, td.Zoom, td.File, time.Now().UnixNano()) needProcess[zoomproc{c: Coord{X: td.Coord.X, Y: td.Coord.Y}.Parent(), m: td.MapID}] = struct{}{} } for z := 1; z <= 5; z++ { process := needProcess needProcess = map[zoomproc]struct{}{} for p := range process { a.updateZoomLevel(p.m, p.c, z) needProcess[zoomproc{p.c.Parent(), p.m}] = struct{}{} } } rw.WriteHeader(200) }