From 291506b5ed49ffbefd9046a9c9f5a297f3e198ab Mon Sep 17 00:00:00 2001 From: Kevin Chabowski Date: Wed, 6 Nov 2013 23:15:51 +0100 Subject: Worlds are now opened by their level.dat and are centered properly. The world spawn will be read from the level.dat and the view will be centered to that position. --- leveldat.go | 41 +++++++++++++++++++++++++++++++++++++++++ listmaps.go | 5 +++-- main.go | 31 +++++++++++++++++++++++++++---- mapwidget.go | 6 ++++++ 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 leveldat.go diff --git a/leveldat.go b/leveldat.go new file mode 100644 index 0000000..51344a8 --- /dev/null +++ b/leveldat.go @@ -0,0 +1,41 @@ +package main + +import ( + "errors" + "fmt" + "github.com/kch42/gonbt/nbt" + "io" +) + +func invalidLevelDat(err error) error { + return fmt.Errorf("Invalid level.dat: %s", err) +} + +func getMapCenter(leveldat io.Reader) (int, int, error) { + lvl, _, err := nbt.ReadGzipdNamedTag(leveldat) + if err != nil { + return 0, 0, err + } + + if lvl.Type != nbt.TAG_Compound { + return 0, 0, invalidLevelDat(errors.New("Root tag has wrong type")) + } + root := lvl.Payload.(nbt.TagCompound) + + data, err := root.GetCompound("Data") + if err != nil { + return 0, 0, invalidLevelDat(err) + } + + x, err := data.GetInt("SpawnX") + if err != nil { + return 0, 0, invalidLevelDat(err) + } + + z, err := data.GetInt("SpawnZ") + if err != nil { + return 0, 0, invalidLevelDat(err) + } + + return int(x), int(z), nil +} diff --git a/listmaps.go b/listmaps.go index ad8a0cc..8a1c088 100644 --- a/listmaps.go +++ b/listmaps.go @@ -42,12 +42,13 @@ func allMaps() map[string]string { } p := path.Join(savesDir, info.Name()) - fi, err := os.Stat(path.Join(p, "level.dat")) + leveldat := path.Join(p, "level.dat") + fi, err := os.Stat(leveldat) if (err != nil) || (!fi.Mode().IsRegular()) { continue } - maps[info.Name()] = path.Join(p, "region") + maps[info.Name()] = leveldat } return maps diff --git a/main.go b/main.go index 50a975d..37f1a1e 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "github.com/mattn/go-gtk/glib" "github.com/mattn/go-gtk/gtk" "os" + "path" ) type GUI struct { @@ -31,23 +32,45 @@ type GUI struct { } func (g *GUI) openWorldDlg() { - dlg := gtk.NewFileChooserDialog("Open World (region directory)", g.window, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, "Open Region dir", gtk.RESPONSE_OK, "Cancel", gtk.RESPONSE_CANCEL) + dlg := gtk.NewFileChooserDialog("Open World (level.dat)", g.window, gtk.FILE_CHOOSER_ACTION_OPEN, "Open", gtk.RESPONSE_OK, "Cancel", gtk.RESPONSE_CANCEL) + filter := gtk.NewFileFilter() + filter.AddPattern("level.dat") + filter.SetName("level.dat") + dlg.AddFilter(filter) if dlg.Run() == gtk.RESPONSE_OK { g.openWorld(dlg.GetFilename()) } dlg.Destroy() } -func (g *GUI) openWorld(path string) { - region, err := mcmap.OpenRegion(path, false) +func readWorld(p string) (*mcmap.Region, int, int, error) { + f, err := os.Open(p) if err != nil { - dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Could not load world %s:\n%s", path, err.Error()) + return nil, 0, 0, err + } + defer f.Close() + + x, z, err := getMapCenter(f) + if err != nil { + return nil, 0, 0, err + } + + dir, _ := path.Split(p) + region, err := mcmap.OpenRegion(path.Join(dir, "region"), false) + return region, x, z, err +} + +func (g *GUI) openWorld(p string) { + region, centerX, centerZ, err := readWorld(p) + if err != nil { + dlg := gtk.NewMessageDialog(g.window, gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, "Could not load world %s:\n%s", p, err.Error()) dlg.Run() dlg.Destroy() } g.menuitemSave.SetSensitive(true) + g.mapw.SetCenter(centerX, centerZ) g.mapw.SetRegion(region) } diff --git a/mapwidget.go b/mapwidget.go index e04b5eb..8fc2b71 100644 --- a/mapwidget.go +++ b/mapwidget.go @@ -63,6 +63,12 @@ func (mw *MapWidget) SetTool(t Tool) { mw.regWrap.SetTool(t) } func (mw *MapWidget) Save() { mw.regWrap.Save() } +func (mw *MapWidget) SetCenter(x, z int) { + mw.offX = x*zoom - mw.w/2 + mw.offZ = z*zoom - mw.h/2 + mw.updateChunkBounds() +} + func (mw *MapWidget) updateChunkBounds() { startX := int(math.Floor(float64(mw.offX) / tileSize)) startZ := int(math.Floor(float64(mw.offZ) / tileSize)) -- cgit v1.2.3-54-g00ecf