world map

This commit is contained in:
Robert Janetzko 2022-05-07 15:08:42 +00:00
parent 190dfdd037
commit eb269cc580
8 changed files with 264 additions and 8 deletions

View file

@ -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)

View file

@ -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(`<script>addRegion('%s', %d, %d, %d, %d, '#FFF')</script>`, x.Name_, x1, y1, x2, y2))
}
return ""
}
var AddMapRegion = func(w *DfWorld, id int) template.HTML {
if x, ok := w.Regions[id]; ok {
r := "<script>"
r += "var polygon = L.polygon(["
r += strings.Join(util.Map(x.Outline(), func(c Coord) string { return fmt.Sprintf(`coord(%d,%d)`, c.X, c.Y-1) }), ",")
r += "], { color : '#fff', opacity: 1, fillOpacity: 0, weight : 1 }).addTo(regionsLayer);\n"
r += "attachTooltip(polygon, '" + x.Name_ + "');\n"
r += "polygon.on('mouseover', function (e) { this.setStyle({weight: 10}); });\n"
r += "polygon.on('mouseout', function (e) { this.setStyle({ weight: 3}); });\n"
fillColor := "transparent"
switch x.Evilness {
case RegionEvilness_Evil:
fillColor = "fuchsia"
case RegionEvilness_Good:
fillColor = "aqua"
}
if fillColor != "transparent" {
r += "var evilPolygon = L.polygon(polygon.getLatLngs(), { color: 'transparent', opacity: 1, fillColor: '" + fillColor + "', fillOpacity: .3, interactive: false });\n"
r += "evilPolygon.addTo(evilnessLayer);\n"
}
r += "</script>"
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(`<script>addMountain('%s', %d, %d, '#666')</script>`, 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(`<script>addWc('%s', %d, %d, '%s')</script>`, x.Name_, line[0].X, line[0].Y, color))
} else {
r := "<script>"
r += "var polyline = L.polyline(["
r += strings.Join(util.Map(x.Line(), func(c Coord) string { return fmt.Sprintf(`coord(%d+0.5,%d-0.5)`, c.X, c.Y) }), ",")
r += "], {color: '" + color + "', opacity: 1, weight: 3}).addTo(constructionsLayer);\n"
r += "attachTooltip(polyline, '" + x.Name_ + "');\n"
r += "polyline.on('mouseover', function (e) { this.setStyle({weight: 10}); });\n"
r += "polyline.on('mouseout', function (e) { this.setStyle({ weight: 3}); });\n"
r += "</script>"
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 {

View file

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

View file

@ -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() {

View file

@ -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

View file

@ -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)
},

View file

@ -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;
}

View file

@ -0,0 +1,34 @@
{{template "layout.html" .}}
{{define "title"}}Legends Browser{{end}}
{{define "content"}}
<div id="map" style="width: 100%; height: 1000px"></div>
{{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 }}