Browse Source

Attempting to get a editor

An editor to modify the world and tiles is needed... I'm not done yet,
we're not rendering the first line right (the panel boarder is being
eaten).
Apollo 8 months ago
parent
commit
d6813a130d
6 changed files with 150 additions and 63 deletions
  1. 18 0
      camera.go
  2. 55 0
      editor.go
  3. 3 0
      go.mod
  4. 4 0
      go.sum
  5. 69 62
      main.go
  6. 1 1
      world.go

+ 18 - 0
camera.go

@@ -1,5 +1,7 @@
 package main
 
+import door "git.red-green.com/RedGreen/doorgo"
+
 type Camera struct {
 	Size *Vec2
 }
@@ -22,3 +24,19 @@ func (c *Camera) debugView(at *Vec2, w *World) string {
 	}
 	return out
 }
+
+func (c *Camera) View(at *Vec2, offset *Vec2, w *World) string {
+	out := ""
+	t := at.Clone()
+	t.X -= c.Size.X / 2
+	t.Y -= c.Size.Y / 2
+	for y := range make([]byte, c.Size.Y) {
+		for x := range make([]byte, c.Size.X) {
+			id := w.Get(uint64(t.X)+uint64(x), uint64(t.Y)+uint64(y))
+			if id != 0 {
+				out += door.GotoS(int(offset.X)+x, int(offset.Y)+y) + door.ColorTextS(w.TileIndex.Tiles[id].Color) + w.TileIndex.Tiles[id].Symbol + door.Reset
+			}
+		}
+	}
+	return out
+}

+ 55 - 0
editor.go

@@ -0,0 +1,55 @@
+package main
+
+import (
+	"fmt"
+
+	door "git.red-green.com/RedGreen/doorgo"
+)
+
+type Editor struct {
+	World  *World
+	Camera *Camera
+	Pos    *Vec2
+}
+
+func NewEditor(w *World, cam_size, pos *Vec2) *Editor {
+	e := &Editor{
+		World: w,
+		Camera: &Camera{
+			Size: cam_size.Clone(),
+		},
+		Pos: pos.Clone(),
+	}
+	if w == nil || cam_size == nil || pos == nil {
+		return nil
+	}
+	return e
+}
+
+func (e *Editor) TileMenu() *door.Menu {
+	m := &door.Menu{
+		Chosen:      0,
+		SelectedR:   door.MakeMenuRender(door.ColorText("BRI WHI ON BLU"), door.ColorText("BRI WHI ON BLU"), door.ColorText("BRI WHI ON BLU"), door.ColorText("BRI WHI ON BLU")),
+		UnselectedR: door.MakeMenuRender(door.ColorText("BRI BLA ON BLA"), door.ColorText("BRI CYA ON BLA"), door.ColorText("BRI WHI ON BLA"), door.ColorText("WHI ON BLA")),
+		Panel: door.Panel{
+			X:           1,
+			Y:           1,
+			Width:       door.Width - 2,
+			Style:       door.SINGLE,
+			BorderColor: door.ColorText("BRI CYA ON BLA"),
+			Title:       " Tiles ",
+			TitleColor:  door.ColorText("BRI WHI ON BLA"),
+			TitleOffset: 4,
+		},
+	}
+	if len(e.World.TileIndex.Tiles) != 0 {
+		for idx, t := range e.World.TileIndex.Tiles {
+			if t == nil {
+				continue
+			}
+			m.AddSelection(fmt.Sprintf("%d", idx), fmt.Sprintf("'%s' in '%s'", t.Symbol, t.Color))
+		}
+	}
+	m.AddSelection("A", "Add Tile")
+	return m
+}

+ 3 - 0
go.mod

@@ -11,8 +11,11 @@ require (
 )
 
 require (
+	git.red-green.com/RedGreen/doorgo v0.0.0-20230521205550-1aab0f75bdd6 // indirect
 	github.com/jinzhu/inflection v1.0.0 // indirect
 	github.com/jinzhu/now v1.1.5 // indirect
 	github.com/mattn/go-sqlite3 v1.14.22 // indirect
+	golang.org/x/sys v0.22.0 // indirect
+	golang.org/x/term v0.22.0 // indirect
 	golang.org/x/text v0.16.0 // indirect
 )

+ 4 - 0
go.sum

@@ -6,6 +6,10 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o
 github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
 golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
 golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
+golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
 golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
 golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
 gorm.io/driver/sqlite v1.5.6 h1:fO/X46qn5NUEEOZtnjJRWRzZMe8nqJiQ9E+0hi+hKQE=

+ 69 - 62
main.go

@@ -1,85 +1,92 @@
 package main
 
 import (
+	"bytes"
 	"fmt"
 	"path"
+	"strings"
+
+	door "git.red-green.com/RedGreen/doorgo"
+)
+
+var (
+	d door.Door
 )
 
 func main() {
-	// The UserDB would be run on the server
-	// But since most/100% of this is examples, we'll setup one up
-	db := &UserDB{}
-	err := db.Open(path.Join("test_data", "test_users.db3"))
+	d.Init("CyberRealms")
+	defer d.Close()
+	d.WriteS(door.Clrscr)
+	w, err := LoadWorld(path.Join("data", "world"))
 	if err != nil {
 		fmt.Println("Err:", err)
-		return
-	}
-	defer db.Close()
-
-	// Example query
-	dummy, err := db.FindUser("Test Dummy")
-	if err != nil {
-		// Of course, we'd ask the user for their name and a password then use those
-		// But for our Test Dummy let's just make a dumb and simple setup
-		err = db.CreateUser("Test Dummy", "12345")
+		w = NewWorld("Overworld", NewVec2(100))
+		err := w.Save(path.Join("data", "world"))
 		if err != nil {
-			fmt.Println("Err:", err)
-			return
-		}
-		dummy, err = db.FindUser("Test Dummy")
-		if err != nil {
-			fmt.Println("Err:", err)
+			d.WriteS(door.ColorTextS("BRI RED ON BLA") + "Err: " + err.Error() + door.Reset + door.CRNL)
+			d.WaitKey(door.Inactivity)
 			return
 		}
 	}
-	//fmt.Printf("%#v\r\n", dummy)
-	// Example verification process
-	// I'd also want to verify they aren't trying to login in 2+ places at once
-	err = dummy.VerifyPassword("12345")
-	if err != nil {
-		fmt.Println("Wrong password?")
-	} else {
-		fmt.Printf("Yay, %s has logged in\r\n", dummy.Name)
-	}
-	fmt.Printf("%s is at %s\r\n", dummy.Name, dummy.Loc.String())
-
-	ti, err := ParseTileIndex(path.Join("test_data", "world1", "tiles.txt"))
-	if err != nil {
-		fmt.Println("Err:", err)
+	editor := NewEditor(w, NewVec2(int64(door.Width-2), int64(door.Height-2)), NewVec2())
+	if editor == nil {
+		d.WriteS(door.ColorTextS("BRI RED ON BLA") + "Err: Failed initializing editor" + door.Reset + door.CRNL)
+		d.WaitKey(door.Inactivity)
 		return
 	}
-	fmt.Printf("Loaded %d tiles from 'world1'\r\n", len(ti.Tiles)-1)
-	for i, t := range ti.Tiles {
-		if i == 0 {
-			continue
-		}
-		fmt.Printf("Id=%d Symbol='%s' Color='%s'\r\n", i, t.Symbol, t.Color)
+	p := door.Panel{
+		X:           1,
+		Y:           1,
+		Width:       door.Width - 2,
+		Style:       door.SINGLE,
+		BorderColor: door.ColorText("WHI ON BLA"),
 	}
-	w, err := LoadWorld(path.Join("test_data", "world1"))
-	if err != nil {
-		fmt.Println("Err:", err)
-		return
+	for range make([]byte, door.Height-2) {
+		p.Lines = append(p.Lines, &door.Line{
+			Text: bytes.NewBufferString(strings.Repeat(" ", door.Width-2)),
+		})
 	}
-	fmt.Println("Loaded", w.Name, "a", w.Width, "x", w.Height)
-	/*err = w.Save(path.Join("test_data", "world2"))
-	if err != nil {
-		fmt.Println("Err:", err)
-		return
-	}*/
-	c := &Camera{Size: NewVec2(20)}
-	fmt.Println(c.debugView(NewVec2(10), w))
-	w2, err := LoadWorld(path.Join("test_data", "world3"))
-	if err != nil {
-		w2 = NewWorld("Test World 3", NewVec2(20))
-		w2.AddTile(".", "BRI GRE ON BLA")
-		w2.AddTile("^", "BRI WHI ON BLA")
-		w2.AddTile("^", "WHI ON BLA")
-		w2.Set(1, 1, 1)
-		err = w2.Save(path.Join("test_data", "world3"))
+	tile_menu := editor.TileMenu()
+EDITOR_LOOP:
+	for {
+		d.Write(p.Output())
+		d.WriteS(editor.Camera.View(editor.Pos, NewVec2(1, 2), editor.World) + door.GotoS(door.Width/2, door.Height/2))
+		r, ext, err := d.WaitKey(door.Inactivity)
 		if err != nil {
-			fmt.Println("Err:", err)
+			d.WriteS(door.ColorTextS("BRI RED ON BLA") + "Err: " + err.Error() + door.Reset + door.CRNL)
+			d.WaitKey(door.Inactivity)
 			return
 		}
+		if ext != door.NOP {
+			switch ext {
+			case door.UP_ARROW:
+				editor.Pos.Translate(0, -1)
+			case door.DOWN_ARROW:
+				editor.Pos.Translate(0, 1)
+			case door.LEFT_ARROW:
+				editor.Pos.Translate(-1, 0)
+			case door.RIGHT_ARROW:
+				editor.Pos.Translate(1, 0)
+			}
+		}
+		if r != 0 {
+			switch r {
+			case 't':
+				fmt.Println("Show the tile menu, and jump to handling options for it")
+				d.Write(tile_menu.Output())
+				d.WaitKey(door.Inactivity)
+			case '5', '\r', '\n':
+				fmt.Println("Allow selecting a tile index number to place a tile at current position")
+				editor.World.Set(uint64(editor.Pos.X), uint64(editor.Pos.Y-1), 1)
+			case 'q':
+				break EDITOR_LOOP
+			}
+		}
+	}
+	err = editor.World.Save(path.Join("data", "world"))
+	if err != nil {
+		d.WriteS(door.ColorTextS("BRI RED ON BLA") + "Err: " + err.Error() + door.Reset + door.CRNL)
+		d.WaitKey(door.Inactivity)
+		return
 	}
-	fmt.Println(c.debugView(NewVec2(10), w2))
 }

+ 1 - 1
world.go

@@ -63,7 +63,7 @@ func LoadWorld(worlddir string) (*World, error) {
 	for _, b := range payload {
 		if b == '\n' {
 			linenum += 1
-			parts := strings.Split(line, " ")
+			parts := strings.Split(strings.TrimSpace(line), " ")
 			if len(parts) != int(w.Width) {
 				return nil, fmt.Errorf("%d]: Failed parsing Map Data, not enough parts (expected=%d, got=%d), '%s'", linenum, w.Width, len(parts), line)
 			}