world map
This commit is contained in:
parent
190dfdd037
commit
eb269cc580
|
@ -3,6 +3,7 @@ package main
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
|
@ -47,11 +48,11 @@ func main() {
|
||||||
if len(*f) > 0 {
|
if len(*f) > 0 {
|
||||||
w, err := model.Parse(*f, nil)
|
w, err := model.Parse(*f, nil)
|
||||||
if err != 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)
|
err = server.StartServer(config, world, static)
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/robertjanetzko/LegendsBrowser2/backend/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
var LinkHf = func(w *DfWorld, id int) template.HTML { return template.HTML((&Context{World: w}).hf(id)) }
|
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 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 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 {
|
var AddMapSite = func(w *DfWorld, id int) template.HTML {
|
||||||
if site, ok := w.Sites[id]; ok {
|
if site, ok := w.Sites[id]; ok {
|
||||||
coords := strings.Split(site.Rectangle, ":")
|
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)) }
|
var AndList = func(s []string) template.HTML { return template.HTML(andList(s)) }
|
||||||
|
|
||||||
func andList(list []string) string {
|
func andList(list []string) string {
|
||||||
|
|
|
@ -87,3 +87,115 @@ func (w *DfWorld) LoadDimensions() {
|
||||||
w.Width, _ = strconv.Atoi(result[0][2])
|
w.Width, _ = strconv.Atoi(result[0][2])
|
||||||
w.Height, _ = strconv.Atoi(result[0][1])
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -46,9 +46,10 @@ func (w *DfWorld) process() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check events texts
|
// check events texts
|
||||||
for _, e := range w.HistoricalEvents {
|
// for _, e := range w.HistoricalEvents {
|
||||||
e.Details.Html(&Context{World: w})
|
// e.Details.Html(&Context{World: w})
|
||||||
}
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *DfWorld) processEvents() {
|
func (w *DfWorld) processEvents() {
|
||||||
|
|
|
@ -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("/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.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 {
|
srv.RegisterWorldPage("/", "index.html", func(p Parms) any {
|
||||||
return &struct {
|
return &struct {
|
||||||
Civilizations map[string][]*model.Entity
|
Civilizations map[string][]*model.Entity
|
||||||
|
|
|
@ -37,7 +37,6 @@ func (srv *DfServer) LoadTemplates() {
|
||||||
"entity": func(id int) template.HTML { return model.LinkEntity(srv.context.world, id) },
|
"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] },
|
"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) },
|
"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] },
|
"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) },
|
"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) },
|
"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) },
|
"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) },
|
"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) },
|
"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 {
|
"events": func(obj any) *model.EventList {
|
||||||
return model.NewEventList(srv.context.world, obj)
|
return model.NewEventList(srv.context.world, obj)
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,11 @@ a {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.leaflet-container {
|
||||||
|
background: rgba(122, 122, 122, 0.1) !important;
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }}
|
Loading…
Reference in New Issue