From 7ea40cbd00f7ddae53a8e43dd018d62ca798f8cf Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Thu, 9 Jul 2026 17:47:39 -0400 Subject: feat(admin): exits to non-existent rooms show on map as ? --- internal/admin/api_map.go | 19 +++++++++- internal/admin/static/map.js | 77 ++++++++++++++++++++++++++++++++------- internal/admin/templates/map.html | 2 +- 3 files changed, 82 insertions(+), 16 deletions(-) (limited to 'internal') diff --git a/internal/admin/api_map.go b/internal/admin/api_map.go index f5fd9ee..6e62d9e 100644 --- a/internal/admin/api_map.go +++ b/internal/admin/api_map.go @@ -175,6 +175,7 @@ func (s *AdminServer) handleMap(w http.ResponseWriter, r *http.Request) { Bidirectional bool `json:"bidirectional"` Hidden bool `json:"hidden"` AlwaysBlocked bool `json:"always_blocked"` + Missing bool `json:"missing"` } type UDLink struct { @@ -243,8 +244,22 @@ func (s *AdminServer) handleMap(w http.ResponseWriter, r *http.Request) { if target <= 0 { continue } - targetCoord, ok := g.Coord[target] - if !ok { + targetCoord, hasCoord := g.Coord[target] + targetExists := s.world.RoomIndex()[target] + + if !targetExists || !hasCoord { + if dir != world.Up && dir != world.Down { + key := linkKey(rid, target) + if !seenLinks[key] { + seenLinks[key] = true + links = append(links, LinkEntry{ + From: rid, + To: target, + Dir: string(dir), + Missing: true, + }) + } + } continue } diff --git a/internal/admin/static/map.js b/internal/admin/static/map.js index e053dda..00230a4 100644 --- a/internal/admin/static/map.js +++ b/internal/admin/static/map.js @@ -277,8 +277,21 @@ function renderMap(data) { if (data.links) { data.links.forEach(function(l) { var fr = roomMap[l.from], tr = roomMap[l.to]; - if (!fr || !tr) return; + if (!fr) return; var x1 = fr.x * CELL + CELL/2, y1 = fr.y * CELL + CELL/2; + if (!tr) { + if (l.missing) { + var dd = gridDirs.find(function(d) { return d.dir === l.dir; }); + if (dd) { + var dx = (fr.x + dd.dx) * CELL + CELL/2; + var dy = (fr.y + dd.dy) * CELL + CELL/2; + g += ''; + g += '?'; + g += '#'+l.to+''; + } + } + return; + } var x2 = tr.x * CELL + CELL/2, y2 = tr.y * CELL + CELL/2; if (l.always_blocked) { g += ''; @@ -2683,32 +2696,70 @@ function updateDelDragTarget(e) { var gp = mouseToGrid(e); if (!gp) return; - var neighbor = occupied[gp.x+','+gp.y]; - if (!neighbor || neighbor === delFromId) return; - var gdx = gp.x - fromRoom.x; var gdy = gp.y - fromRoom.y; if (Math.abs(gdx) > 1 || Math.abs(gdy) > 1) return; if (gdx === 0 && gdy === 0) return; - if (!gridDeltaToDir(gdx, gdy)) return; + var dir = gridDeltaToDir(gdx, gdy); + if (!dir) return; - delTargetId = neighbor; - applyDelHighlight(delFromId, delTargetId); + var neighbor = occupied[gp.x+','+gp.y]; + if (neighbor && neighbor !== delFromId) { + delTargetId = neighbor; + applyDelHighlight(delFromId, delTargetId); + return; + } + + if (mapData && mapData.links) { + for (var i = 0; i < mapData.links.length; i++) { + var lk = mapData.links[i]; + if (lk.from === delFromId && lk.missing && lk.dir === dir) { + delTargetId = lk.to; + applyDelHighlight(delFromId, delTargetId); + return; + } + } + } } function applyDelHighlight(fromId, toId) { clearDelHighlight(); var fromEl = document.querySelector('.rm[data-id="'+fromId+'"]'); - var toEl = document.querySelector('.rm[data-id="'+toId+'"]'); var fromRoom = roomMap[fromId]; + if (!fromEl || !fromRoom) return; + + var toEl = document.querySelector('.rm[data-id="'+toId+'"]'); var toRoom = roomMap[toId]; - if (!fromEl || !toEl || !fromRoom || !toRoom) return; + var tx, ty; + + if (!toRoom) { + var found = false; + if (mapData && mapData.links) { + for (var i = 0; i < mapData.links.length; i++) { + var l = mapData.links[i]; + if (l.from === fromId && l.to === toId && l.missing) { + var dd = gridDirs.find(function(d) { return d.dir === l.dir; }); + if (dd) { + tx = (fromRoom.x + dd.dx) * CELL + CELL/2; + ty = (fromRoom.y + dd.dy) * CELL + CELL/2; + found = true; + } + break; + } + } + } + if (!found) return; + } else { + if (!toEl) return; + tx = toRoom.x * CELL + CELL/2; + ty = toRoom.y * CELL + CELL/2; + toEl.setAttribute('stroke', '#f55'); + toEl.setAttribute('stroke-width', '3'); + } fromEl.setAttribute('stroke', '#f55'); fromEl.setAttribute('stroke-width', '3'); - toEl.setAttribute('stroke', '#f55'); - toEl.setAttribute('stroke-width', '3'); var g = document.querySelector('#mapSvg g'); if (!g) return; @@ -2717,8 +2768,8 @@ function applyDelHighlight(fromId, toId) { line.id = '__dl_line'; line.setAttribute('x1', fromRoom.x * CELL + CELL/2); line.setAttribute('y1', fromRoom.y * CELL + CELL/2); - line.setAttribute('x2', toRoom.x * CELL + CELL/2); - line.setAttribute('y2', toRoom.y * CELL + CELL/2); + line.setAttribute('x2', tx); + line.setAttribute('y2', ty); line.setAttribute('stroke', '#f55'); line.setAttribute('stroke-width', '3'); line.setAttribute('stroke-dasharray', '6,3'); diff --git a/internal/admin/templates/map.html b/internal/admin/templates/map.html index eb95db7..0915aaa 100644 --- a/internal/admin/templates/map.html +++ b/internal/admin/templates/map.html @@ -1,6 +1,6 @@ {{define "body-map"}}
-
+