diff --git a/backend/main.go b/backend/main.go index 0e3b6aa..0283d66 100644 --- a/backend/main.go +++ b/backend/main.go @@ -3,6 +3,7 @@ package main import ( "embed" "flag" + "fmt" "log" "net/http" _ "net/http/pprof" @@ -47,11 +48,11 @@ func main() { if len(*f) > 0 { w, err := model.Parse(*f, nil) if err != nil { - log.Fatal(err) + fmt.Println(err) + } else { + runtime.GC() + world = w } - - runtime.GC() - world = w } err = server.StartServer(config, world, static) diff --git a/backend/model/functions.go b/backend/model/functions.go index f5f9613..f364036 100644 --- a/backend/model/functions.go +++ b/backend/model/functions.go @@ -6,6 +6,8 @@ import ( "regexp" "strconv" "strings" + + "github.com/robertjanetzko/LegendsBrowser2/backend/util" ) var LinkHf = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).hf(id)) } @@ -30,6 +32,47 @@ var LinkMountain = func(w *DfWorld, id int) template.HTML { return template.HTML var LinkLandmass = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).landmass(id)) } var LinkRiver = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).river(id)) } +var AddMapLandmass = func(w *DfWorld, id int) template.HTML { + if x, ok := w.Landmasses[id]; ok { + c1 := strings.Split(x.Coord1, ",") + x1, _ := strconv.Atoi(c1[0]) + y1, _ := strconv.Atoi(c1[1]) + c2 := strings.Split(x.Coord2, ",") + x2, _ := strconv.Atoi(c2[0]) + y2, _ := strconv.Atoi(c2[1]) + return template.HTML(fmt.Sprintf(``, x.Name_, x1, y1, x2, y2)) + } + return "" +} + +var AddMapRegion = func(w *DfWorld, id int) template.HTML { + if x, ok := w.Regions[id]; ok { + r := "" + return template.HTML(r) + } + return "" +} + var AddMapSite = func(w *DfWorld, id int) template.HTML { if site, ok := w.Sites[id]; ok { coords := strings.Split(site.Rectangle, ":") @@ -45,6 +88,41 @@ var AddMapSite = func(w *DfWorld, id int) template.HTML { } } +var AddMapMountain = func(w *DfWorld, id int) template.HTML { + if m, ok := w.MountainPeaks[id]; ok { + c1 := strings.Split(m.Coords, ",") + x, _ := strconv.Atoi(c1[0]) + y, _ := strconv.Atoi(c1[1]) + return template.HTML(fmt.Sprintf(``, m.Name_, x, y)) + } + return "" +} + +var AddMapWorldConstruction = func(w *DfWorld, id int) template.HTML { + if x, ok := w.WorldConstructions[id]; ok { + color := util.If(x.Type_ == WorldConstructionType_Tunnel, "#000", "#fff") + line := x.Line() + if len(line) == 1 { + return template.HTML(fmt.Sprintf(``, x.Name_, line[0].X, line[0].Y, color)) + } else { + r := "" + return template.HTML(r) + } + } + return "" +} + +var AddMapRiver = func(w *DfWorld, id int) template.HTML { + return "" +} + var AndList = func(s []string) template.HTML { return template.HTML(andList(s)) } func andList(list []string) string { diff --git a/backend/model/map.go b/backend/model/map.go index 611ebc7..3c7e4e6 100644 --- a/backend/model/map.go +++ b/backend/model/map.go @@ -87,3 +87,115 @@ func (w *DfWorld) LoadDimensions() { w.Width, _ = strconv.Atoi(result[0][2]) w.Height, _ = strconv.Atoi(result[0][1]) } + +type Coord struct { + X, Y int +} + +func Coords(s string) []Coord { + var coords []Coord + for _, c := range strings.Split(s, "|") { + if c == "" { + continue + } + d := strings.Split(c, ",") + x, _ := strconv.Atoi(d[0]) + y, _ := strconv.Atoi(d[1]) + coords = append(coords, Coord{X: x, Y: y}) + } + return coords +} + +func maxCoords(coords []Coord) Coord { + var max Coord + for _, c := range coords { + if c.X > max.X { + max.X = c.X + } + if c.Y > max.Y { + max.Y = c.Y + } + } + return max +} + +func (r *Region) Outline() []Coord { + var outline []Coord + // if (cacheOutline != null) + // return cacheOutline; + + /* draw the region in a matrix */ + coords := Coords(r.Coords) + max := maxCoords(coords) + + var region = make([][]bool, max.X+3) + for i := range region { + region[i] = make([]bool, max.Y+3) + } + for _, c := range coords { + region[c.X+1][c.Y+1] = true + } + + var curdir, prevdir rune + curdir = 'n' + if len(coords) == 1 || coords[0].X == coords[1].X-1 { + curdir = 'e' + } + + x0 := coords[0].X + 1 + y0 := coords[0].Y + 1 + x := x0 + y := y0 + + /* follow the outline by keeping the right hand inside */ +Loop: + for { + if !(x != x0 || y != y0 || prevdir == 0) { + break Loop + } + + prevdir = curdir + switch { + case curdir == 'n' && y > 1: + y -= 1 + if region[x-1][y-1] { + curdir = 'w' + } else if !region[x][y-1] { + curdir = 'e' + } + case curdir == 's' && y < max.Y+2: + y += 1 + if region[x][y] { + curdir = 'e' + } else if !region[x-1][y] { + curdir = 'w' + } + case curdir == 'w' && x > 1: + x -= 1 + if region[x-1][y] { + curdir = 's' + } else if !region[x-1][y-1] { + curdir = 'n' + } + case curdir == 'e' && x < max.X+2: + x += 1 + if region[x][y-1] { + curdir = 'n' + } else if !region[x][y] { + curdir = 's' + } + } + if curdir != prevdir { + /* change of direction: record point */ + outline = append(outline, Coord{X: x - 1, Y: y - 1}) + if len(outline) > 256*10 { + break Loop + } + } + } + return outline +} + +func (x *WorldConstruction) Line() []Coord { + return Coords(x.Coords) +} diff --git a/backend/model/process.go b/backend/model/process.go index 43b40fc..c4f6f3c 100644 --- a/backend/model/process.go +++ b/backend/model/process.go @@ -46,9 +46,10 @@ func (w *DfWorld) process() { } // check events texts - for _, e := range w.HistoricalEvents { - e.Details.Html(&Context{World: w}) - } + // for _, e := range w.HistoricalEvents { + // e.Details.Html(&Context{World: w}) + // } + } func (w *DfWorld) processEvents() { diff --git a/backend/server/server.go b/backend/server/server.go index cc43aba..f987bcf 100644 --- a/backend/server/server.go +++ b/backend/server/server.go @@ -124,6 +124,24 @@ func StartServer(config *Config, world *model.DfWorld, static embed.FS) error { srv.RegisterWorldResourcePage("/collection/{id}", "collection.html", func(id int) any { return srv.context.world.HistoricalEventCollections[id] }) srv.RegisterWorldResourcePage("/popover/collection/{id}", "popoverCollection.html", func(id int) any { return srv.context.world.HistoricalEventCollections[id] }) + srv.RegisterWorldPage("/worldmap", "worldMap.html", func(p Parms) any { + return &struct { + Landmasses map[int]*model.Landmass + Regions map[int]*model.Region + Sites map[int]*model.Site + MountainPeaks map[int]*model.MountainPeak + WorldConstructions map[int]*model.WorldConstruction + Rivers []*model.River + }{ + Landmasses: srv.context.world.Landmasses, + Regions: srv.context.world.Regions, + Sites: srv.context.world.Sites, + MountainPeaks: srv.context.world.MountainPeaks, + WorldConstructions: srv.context.world.WorldConstructions, + Rivers: srv.context.world.Rivers, + } + }) + srv.RegisterWorldPage("/", "index.html", func(p Parms) any { return &struct { Civilizations map[string][]*model.Entity diff --git a/backend/server/templates.go b/backend/server/templates.go index efcd829..dca7e72 100644 --- a/backend/server/templates.go +++ b/backend/server/templates.go @@ -37,7 +37,6 @@ func (srv *DfServer) LoadTemplates() { "entity": func(id int) template.HTML { return model.LinkEntity(srv.context.world, id) }, "getEntity": func(id int) *model.Entity { return srv.context.world.Entities[id] }, "site": func(id int) template.HTML { return model.LinkSite(srv.context.world, id) }, - "addSite": func(id int) template.HTML { return model.AddMapSite(srv.context.world, id) }, "getSite": func(id int) *model.Site { return srv.context.world.Sites[id] }, "structure": func(siteId, id int) template.HTML { return model.LinkStructure(srv.context.world, siteId, id) }, "region": func(id int) template.HTML { return model.LinkRegion(srv.context.world, id) }, @@ -53,6 +52,14 @@ func (srv *DfServer) LoadTemplates() { "landmass": func(id int) template.HTML { return model.LinkLandmass(srv.context.world, id) }, "mountain": func(id int) template.HTML { return model.LinkMountain(srv.context.world, id) }, "river": func(id int) template.HTML { return model.LinkRiver(srv.context.world, id) }, + + "addLandmass": func(id int) template.HTML { return model.AddMapLandmass(srv.context.world, id) }, + "addRegion": func(id int) template.HTML { return model.AddMapRegion(srv.context.world, id) }, + "addSite": func(id int) template.HTML { return model.AddMapSite(srv.context.world, id) }, + "addMountain": func(id int) template.HTML { return model.AddMapMountain(srv.context.world, id) }, + "addWorldConstruction": func(id int) template.HTML { return model.AddMapWorldConstruction(srv.context.world, id) }, + "addRiver": func(id int) template.HTML { return model.AddMapRiver(srv.context.world, id) }, + "events": func(obj any) *model.EventList { return model.NewEventList(srv.context.world, obj) }, diff --git a/backend/static/css/legends.css b/backend/static/css/legends.css index 47068c8..a7c527c 100644 --- a/backend/static/css/legends.css +++ b/backend/static/css/legends.css @@ -3,6 +3,11 @@ a { white-space: nowrap; } +.leaflet-container { + background: rgba(122, 122, 122, 0.1) !important; + outline: 0; +} + .popover { max-width: fit-content; } diff --git a/backend/templates/worldMap.html b/backend/templates/worldMap.html new file mode 100644 index 0000000..992ce73 --- /dev/null +++ b/backend/templates/worldMap.html @@ -0,0 +1,34 @@ +{{template "layout.html" .}} + +{{define "title"}}Legends Browser{{end}} + +{{define "content"}} + +
+{{initMap}} + +{{- range .Landmasses }} +{{ addLandmass .Id }} +{{- end }} + +{{- range .Regions }} +{{ addRegion .Id }} +{{- end }} + +{{- range .Sites }} +{{ addSite .Id }} +{{- end }} + +{{- range .MountainPeaks }} +{{ addMountain .Id }} +{{- end }} + +{{- range .WorldConstructions }} +{{ addWorldConstruction .Id }} +{{- end }} + +{{- range $id, $r := .Rivers }} +{{ addRiver $id }} +{{- end }} + +{{- end }} \ No newline at end of file