From 98bdef072c843fdd8ccdf85a9b54ab9d32d34187 Mon Sep 17 00:00:00 2001
From: historia <[not public]>
Date: Tue, 30 Jun 2026 04:43:54 -0400
Subject: slop refactor
---
internal/admin/api_map.go | 48 +++--------
internal/admin/api_rooms.go | 70 ++++++----------
internal/admin/server.go | 39 ++++++---
internal/admin/static/map.js | 184 +++++++++++++++++++++++--------------------
internal/admin/undo.go | 2 +-
5 files changed, 165 insertions(+), 178 deletions(-)
(limited to 'internal/admin')
diff --git a/internal/admin/api_map.go b/internal/admin/api_map.go
index 5de41a7..7298f1e 100644
--- a/internal/admin/api_map.go
+++ b/internal/admin/api_map.go
@@ -44,7 +44,6 @@ func (s *AdminServer) handleMap(w http.ResponseWriter, r *http.Request) {
Y int `json:"y"`
Name string `json:"name"`
Color string `json:"color"`
- Symbol string `json:"symbol"`
}
type LinkEntry struct {
@@ -249,47 +248,22 @@ func findDisconnectedRooms(s *AdminServer, dir string, seed int, g world.RoomGri
func listRoomIDsInDir(s *AdminServer, dir string) []int {
base := filepath.Join(s.dataDir, "rooms")
- var dirs []string
- if dir == "" {
- dirs = append(dirs, base)
- entries, err := os.ReadDir(base)
- if err != nil {
- return nil
- }
- for _, e := range entries {
- if e.IsDir() {
- dirs = append(dirs, filepath.Join(base, e.Name()))
- subE, err := os.ReadDir(filepath.Join(base, e.Name()))
- if err != nil {
- continue
- }
- for _, se := range subE {
- if se.IsDir() {
- dirs = append(dirs, filepath.Join(base, e.Name(), se.Name()))
- }
- }
- }
- }
- } else {
- dirs = append(dirs, filepath.Join(base, dir))
+ walkRoot := base
+ if dir != "" {
+ walkRoot = filepath.Join(base, dir)
}
var ids []int
- for _, d := range dirs {
- entries, err := os.ReadDir(d)
- if err != nil {
- continue
+ filepath.WalkDir(walkRoot, func(path string, d os.DirEntry, err error) error {
+ if err != nil || d.IsDir() || filepath.Ext(d.Name()) != ".yaml" {
+ return nil
}
- for _, e := range entries {
- if e.IsDir() || filepath.Ext(e.Name()) != ".yaml" {
- continue
- }
- id, err := strconv.Atoi(e.Name()[:len(e.Name())-5])
- if err != nil {
- continue
- }
+ name := d.Name()
+ id, convErr := strconv.Atoi(name[:len(name)-5])
+ if convErr == nil && id > 0 {
ids = append(ids, id)
}
- }
+ return nil
+ })
return ids
}
diff --git a/internal/admin/api_rooms.go b/internal/admin/api_rooms.go
index b60aefc..a477cc3 100644
--- a/internal/admin/api_rooms.go
+++ b/internal/admin/api_rooms.go
@@ -106,7 +106,7 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) {
})
}
- exits[string(opp)] = float64(*linkFrom)
+ exits[string(opp)] = *linkFrom
}
}
@@ -161,7 +161,7 @@ func (s *AdminServer) handleRoomByID(w http.ResponseWriter, r *http.Request) {
return
}
m["id"] = id
- writeJSON(w, map[string]any{"room": m, "path": path, "file": path, "raw": string(data)})
+ writeJSON(w, map[string]any{"room": m, "path": path, "file": path})
case http.MethodPut:
path, ok := s.world.GetRoomPath(id)
@@ -298,45 +298,27 @@ func (s *AdminServer) handleRoomDirs(w http.ResponseWriter, r *http.Request) {
return
}
base := filepath.Join(s.dataDir, "rooms")
- entries, err := os.ReadDir(base)
- if err != nil {
- writeJSON(w, []string{""})
- return
- }
dirs := []string{""}
- for _, e := range entries {
- if !e.IsDir() {
- continue
- }
- if hasYAMLFiles(filepath.Join(base, e.Name())) {
- dirs = append(dirs, e.Name())
- }
- subEntries, err := os.ReadDir(filepath.Join(base, e.Name()))
- if err != nil {
- continue
- }
- for _, se := range subEntries {
- if se.IsDir() && hasYAMLFiles(filepath.Join(base, e.Name(), se.Name())) {
- dirs = append(dirs, e.Name()+"/"+se.Name())
+ filepath.WalkDir(base, func(path string, d os.DirEntry, err error) error {
+ if err != nil || !d.IsDir() || path == base {
+ return nil
+ }
+ entries, rdErr := os.ReadDir(path)
+ if rdErr != nil {
+ return nil
+ }
+ for _, e := range entries {
+ if !e.IsDir() && filepath.Ext(e.Name()) == ".yaml" {
+ rel, _ := filepath.Rel(base, path)
+ dirs = append(dirs, rel)
+ return nil
}
}
- }
+ return nil
+ })
writeJSON(w, dirs)
}
-func hasYAMLFiles(dir string) bool {
- entries, err := os.ReadDir(dir)
- if err != nil {
- return false
- }
- for _, e := range entries {
- if !e.IsDir() && filepath.Ext(e.Name()) == ".yaml" {
- return true
- }
- }
- return false
-}
-
func (s *AdminServer) handleRoomLink(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodPost:
@@ -377,10 +359,14 @@ func (s *AdminServer) handleRoomLink(w http.ResponseWriter, r *http.Request) {
cA, okA := grid.Coord[body.From]
cB, okB := grid.Coord[body.To]
- if !okA || !okB || cA[2] != cB[2] {
- writeJSON(w, map[string]any{"error": "rooms must be on same z-level"})
- return
- }
+ if !okA || !okB {
+ writeJSON(w, map[string]any{"error": "one or both rooms are not reachable from the seed room"})
+ return
+ }
+ if cA[2] != cB[2] {
+ writeJSON(w, map[string]any{"error": "rooms must be on same z-level"})
+ return
+ }
dx, dy := cB[0]-cA[0], cB[1]-cA[1]
for d, delta := range world.DirectionDeltas3D {
if delta[0] == dx && delta[1] == dy && delta[2] == 0 {
@@ -510,12 +496,6 @@ func (s *AdminServer) handleRoomLink(w http.ResponseWriter, r *http.Request) {
writeJSON(w, map[string]any{"error": "both rooms not found"})
return
}
- if (errA != nil && roomA == nil) {
- roomA = nil
- }
- if (errB != nil && roomB == nil) {
- roomB = nil
- }
var dir, oppDir world.ExitDir
if roomA != nil {
diff --git a/internal/admin/server.go b/internal/admin/server.go
index 8facc4a..823d7ba 100644
--- a/internal/admin/server.go
+++ b/internal/admin/server.go
@@ -34,6 +34,7 @@ var embedded embed.FS
type AdminServer struct {
cfg *config.Config
+ useTLS bool
accountStore *player.AccountStore
world *world.World
itemStore *item.ItemStore
@@ -46,7 +47,7 @@ type AdminServer struct {
cookieSecret []byte
}
-func NewServer(cfg *config.Config, accountStore *player.AccountStore, w *world.World, is *item.ItemStore, os *object.ObjectStore, ms *world.MobStore, dataDir string) (*AdminServer, error) {
+func NewServer(cfg *config.Config, useTLS bool, accountStore *player.AccountStore, w *world.World, is *item.ItemStore, os *object.ObjectStore, ms *world.MobStore, dataDir string) (*AdminServer, error) {
secret := make([]byte, 32)
if _, err := rand.Read(secret); err != nil {
return nil, fmt.Errorf("cookie secret: %w", err)
@@ -62,13 +63,24 @@ func NewServer(cfg *config.Config, accountStore *player.AccountStore, w *world.W
return nil, fmt.Errorf("parse templates: %w", err)
}
- cert, err := loadOrGenerateCert(cfg)
- if err != nil {
- return nil, fmt.Errorf("admin cert: %w", err)
+ var port int
+ if useTLS {
+ port = cfg.AdminHTTPS.Port
+ } else {
+ port = cfg.AdminHTTP.Port
+ }
+
+ var cert tls.Certificate
+ if useTLS {
+ cert, err = loadOrGenerateCert(cfg)
+ if err != nil {
+ return nil, fmt.Errorf("admin cert: %w", err)
+ }
}
s := &AdminServer{
cfg: cfg,
+ useTLS: useTLS,
accountStore: accountStore,
world: w,
itemStore: is,
@@ -159,12 +171,14 @@ func NewServer(cfg *config.Config, accountStore *player.AccountStore, w *world.W
})
s.httpServer = &http.Server{
- Addr: fmt.Sprintf(":%d", cfg.AdminHTTPS.Port),
+ Addr: fmt.Sprintf(":%d", port),
Handler: mux,
- TLSConfig: &tls.Config{
+ }
+ if useTLS {
+ s.httpServer.TLSConfig = &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
- },
+ }
}
return s, nil
@@ -175,8 +189,11 @@ func (s *AdminServer) ListenAndServe() error {
if err != nil {
return fmt.Errorf("admin listen: %w", err)
}
- tlsLn := tls.NewListener(ln, s.httpServer.TLSConfig)
- return s.httpServer.Serve(tlsLn)
+ if s.useTLS {
+ tlsLn := tls.NewListener(ln, s.httpServer.TLSConfig)
+ return s.httpServer.Serve(tlsLn)
+ }
+ return s.httpServer.Serve(ln)
}
func (s *AdminServer) authMiddleware(next http.Handler) http.Handler {
@@ -228,7 +245,7 @@ func (s *AdminServer) setAuthCookie(w http.ResponseWriter, account string) {
Value: account + ":" + sig,
Path: "/",
HttpOnly: true,
- Secure: true,
+ Secure: s.useTLS,
SameSite: http.SameSiteStrictMode,
MaxAge: 86400,
})
@@ -270,7 +287,7 @@ func (s *AdminServer) handleLogout(w http.ResponseWriter, r *http.Request) {
Path: "/",
MaxAge: -1,
HttpOnly: true,
- Secure: true,
+ Secure: s.useTLS,
})
http.Redirect(w, r, "/login", http.StatusFound)
}
diff --git a/internal/admin/static/map.js b/internal/admin/static/map.js
index cd53bed..85364d5 100644
--- a/internal/admin/static/map.js
+++ b/internal/admin/static/map.js
@@ -47,7 +47,7 @@ function loadMap() {
if (currentDir) url += '&dir=' + encodeURIComponent(currentDir);
var wasDirChange = dirChangedByUser;
dirChangedByUser = false;
- API.get(url).then(function(data) {
+ return API.get(url).then(function(data) {
mapData = data;
if (!currentDir && data.dir) {
currentDir = data.dir;
@@ -64,11 +64,11 @@ function loadMap() {
}
function blendColors(colorA, colorB) {
+ if (!colorA && !colorB) return '#666666';
+ if (!colorB) return xtermToCss(parseXtermIdx(colorA));
+ if (!colorA) return xtermToCss(parseXtermIdx(colorB));
var idxA = parseXtermIdx(colorA);
var idxB = parseXtermIdx(colorB);
- if (colorA && !colorB) return xtermToCss(idxA);
- if (!colorA && colorB) return xtermToCss(idxB);
- if (!colorA && !colorB) return '#666666';
var rgbA = xtermToRGB(idxA);
var rgbB = xtermToRGB(idxB);
var r = Math.round((rgbA[0] + rgbB[0]) / 2);
@@ -90,17 +90,21 @@ function renderMap(data) {
var W = container.clientWidth;
var H = container.clientHeight;
- roomMap = {};
- if (data.rooms) data.rooms.forEach(function(r) { roomMap[r.id] = r; });
-
- occupied = {};
- if (data.rooms) data.rooms.forEach(function(r) { occupied[r.x+','+r.y] = r.id; });
-
+ roomMap = {}; occupied = {};
upTarget = {}; downTarget = {};
- if (data.upLinks) data.upLinks.forEach(function(l) { upTarget[l.from] = l.to; });
- if (data.downLinks) data.downLinks.forEach(function(l) { downTarget[l.from] = l.to; });
+ var hasUp = {}, hasDown = {};
+
+ if (data.rooms) data.rooms.forEach(function(r) {
+ roomMap[r.id] = r;
+ occupied[r.x+','+r.y] = r.id;
+ });
+ if (data.upLinks) data.upLinks.forEach(function(l) {
+ upTarget[l.from] = l.to; hasUp[l.from] = true;
+ });
+ if (data.downLinks) data.downLinks.forEach(function(l) {
+ downTarget[l.from] = l.to; hasDown[l.from] = true;
+ });
- var svgNS = 'http://www.w3.org/2000/svg';
var g = '';
if (data.links) {
@@ -109,16 +113,11 @@ function renderMap(data) {
if (!fr || !tr) return;
var x1 = fr.x * CELL + CELL/2, y1 = fr.y * CELL + CELL/2;
var x2 = tr.x * CELL + CELL/2, y2 = tr.y * CELL + CELL/2;
- var c = blendColors(fr.color, tr.color);
- c = c.replace('#','');
+ var c = blendColors(fr.color, tr.color).replace('#','');
g += '