diff --git a/subcommands/world/map_item.go b/subcommands/world/map_item.go index c032ddc..1c57001 100644 --- a/subcommands/world/map_item.go +++ b/subcommands/world/map_item.go @@ -41,6 +41,25 @@ var MAP_ITEM_PACKET packet.InventoryContent = packet.InventoryContent{ }, } +func (m *MapUI) get_bounds() (min, max protocol.ChunkPos) { + // get the chunk coord bounds + for _ch := range m.renderedChunks { + if _ch.X() < min.X() { + min[0] = _ch.X() + } + if _ch.Z() < min.Z() { + min[1] = _ch.Z() + } + if _ch.X() > max.X() { + max[0] = _ch.X() + } + if _ch.Z() > max.Z() { + max[1] = _ch.Z() + } + } + return +} + type RenderElem struct { pos protocol.ChunkPos ch *chunk.Chunk @@ -149,32 +168,11 @@ func (m *MapUI) Redraw() { } } - // get the chunk coord bounds - min := protocol.ChunkPos{} - max := protocol.ChunkPos{} - for _ch := range m.renderedChunks { - if _ch.X() < min.X() { - min[0] = _ch.X() - } - if _ch.Z() < min.Z() { - min[1] = _ch.Z() - } - if _ch.X() > max.X() { - max[0] = _ch.X() - } - if _ch.Z() > max.Z() { - max[1] = _ch.Z() - } - } - middle := protocol.ChunkPos{ int32(m.w.PlayerPos.Position.X()), int32(m.w.PlayerPos.Position.Z()), } - chunks_x := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate - chunks_y := int(max[1] - min[1] + 1) - // total_width := 32 * math.Ceil(float64(chunks_x)/32) chunks_per_line := float64(128 / m.zoomLevel) px_per_block := 128 / chunks_per_line / 16 // how many pixels per block @@ -202,29 +200,39 @@ func (m *MapUI) Redraw() { draw_full := false if draw_full { - img2 := image.NewRGBA(image.Rect(0, 0, chunks_x*16, chunks_y*16)) - - middle_block_x := chunks_x / 2 * 16 - middle_block_y := chunks_y / 2 * 16 - - for pos := range m.renderedChunks { - px_pos := image.Point{ - X: int(pos.X()*16) - middle_block_x + img2.Rect.Dx(), - Y: int(pos.Z()*16) - middle_block_y + img2.Rect.Dy(), - } - draw.Draw(img2, image.Rect( - px_pos.X, - px_pos.Y, - px_pos.X+16, - px_pos.Y+16, - ), m.renderedChunks[pos], image.Point{}, draw.Src) - } + img2 := m.ToImage() buf := bytes.NewBuffer(nil) bmp.Encode(buf, img2) os.WriteFile("test.bmp", buf.Bytes(), 0o777) } } +func (m *MapUI) ToImage() *image.RGBA { + // get the chunk coord bounds + min, max := m.get_bounds() + chunks_x := int(max[0] - min[0] + 1) // how many chunk lengths is x coordinate + chunks_y := int(max[1] - min[1] + 1) + + img2 := image.NewRGBA(image.Rect(0, 0, chunks_x*16, chunks_y*16)) + + middle_block_x := chunks_x / 2 * 16 + middle_block_y := chunks_y / 2 * 16 + + for pos := range m.renderedChunks { + px_pos := image.Point{ + X: int(pos.X()*16) - middle_block_x + img2.Rect.Dx(), + Y: int(pos.Z()*16) - middle_block_y + img2.Rect.Dy(), + } + draw.Draw(img2, image.Rect( + px_pos.X, + px_pos.Y, + px_pos.X+16, + px_pos.Y+16, + ), m.renderedChunks[pos], image.Point{}, draw.Src) + } + return img2 +} + func (m *MapUI) SetChunk(pos protocol.ChunkPos, ch *chunk.Chunk) { m.renderQueue.Enqueue(&RenderElem{pos, ch}) m.SchedRedraw() diff --git a/subcommands/world/world.go b/subcommands/world/world.go index ee4f6b2..a8cb83c 100644 --- a/subcommands/world/world.go +++ b/subcommands/world/world.go @@ -8,6 +8,7 @@ import ( "hash/crc32" "image" "image/draw" + "image/png" "os" "path" "strconv" @@ -53,6 +54,7 @@ type WorldState struct { ServerName string worldCounter int withPacks bool + saveImage bool packs map[string]*resource.Pack PlayerPos TPlayerPos @@ -106,6 +108,7 @@ type WorldCMD struct { Address string packs bool enableVoid bool + saveImage bool } func (*WorldCMD) Name() string { return "worlds" } @@ -115,6 +118,7 @@ func (p *WorldCMD) SetFlags(f *flag.FlagSet) { f.StringVar(&p.Address, "address", "", "remote server address") f.BoolVar(&p.packs, "packs", false, "save resourcepacks to the worlds") f.BoolVar(&p.enableVoid, "void", true, "if false, saves with default flat generator") + f.BoolVar(&p.saveImage, "image", false, "saves an png of the map at the end") } func (c *WorldCMD) Usage() string { @@ -138,6 +142,7 @@ func (c *WorldCMD) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{ w.voidgen = c.enableVoid w.ServerName = hostname w.withPacks = c.packs + w.saveImage = c.saveImage w.ctx = ctx proxy := utils.NewProxy(logrus.StandardLogger()) @@ -424,6 +429,11 @@ func (w *WorldState) SaveAndReset() { utils.UnpackZip(bytes.NewReader(data), int64(len(data)), pack_folder) } + if w.saveImage { + f, _ := os.Create(folder + ".png") + png.Encode(f, w.ui.ToImage()) + } + // zip it filename := folder + ".mcworld"