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 10 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)
 			}