From 74803657d587b1f93b739c1ee25bb8d62df95413 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Tue, 7 Jul 2026 21:22:39 -0400 Subject: fix: agility course creation fixed and improved in admin web gui --- internal/admin/api_rooms.go | 78 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 8 deletions(-) (limited to 'internal/admin/api_rooms.go') diff --git a/internal/admin/api_rooms.go b/internal/admin/api_rooms.go index 49a6601..0925f8b 100644 --- a/internal/admin/api_rooms.go +++ b/internal/admin/api_rooms.go @@ -48,6 +48,8 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { var linkFrom *int var linkDir *string var linkOneWay bool + var linkHidden bool + var linkBlocked bool if v, ok := m["link_from"]; ok { if f, ok := v.(float64); ok { lf := int(f) @@ -68,6 +70,18 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { } delete(m, "link_oneway") } + if v, ok := m["link_hidden"]; ok { + if b, ok := v.(bool); ok { + linkHidden = b + } + delete(m, "link_hidden") + } + if v, ok := m["link_blocked"]; ok { + if b, ok := v.(bool); ok { + linkBlocked = b + } + delete(m, "link_blocked") + } fromID := 0 if linkFrom != nil { @@ -80,6 +94,46 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { } m["id"] = id + if linkFrom != nil && linkDir != nil && *linkDir != "" { + dir := world.ExitDir(strings.ToLower(*linkDir)) + opp, validDir := world.OppositeExit[dir] + if validDir { + conflicts := 0 + world.BuildGrid(s.cfg.StartingRoom, func(rid int) (*world.Room, bool) { + if rid == id { + ex := make(map[world.ExitDir]world.ExitDef) + if !linkOneWay { + ex[opp] = world.ExitDef{Room: *linkFrom} + } + return &world.Room{Exits: ex}, true + } + r, err := s.world.LoadRoom(rid) + if err != nil { + return nil, false + } + if rid == *linkFrom { + rc := *r + rc.Exits = make(map[world.ExitDir]world.ExitDef, len(r.Exits)+1) + for k, v := range r.Exits { + rc.Exits[k] = v + } + rc.Exits[dir] = world.ExitDef{Room: id} + return &rc, true + } + return r, true + }, nil, nil, func(gc world.GridConflict) { + conflicts++ + }) + if conflicts > 0 { + writeJSON(w, map[string]any{"error": fmt.Sprintf("Add Next Step: that grid spot is already occupied — room would cause map overlap")}) + return + } + } else { + writeJSON(w, map[string]any{"error": fmt.Sprintf("invalid direction: %s", *linkDir)}) + return + } + } + exits, _ := m["exits"].(map[string]any) if exits == nil { exits = make(map[string]any) @@ -100,7 +154,7 @@ func (s *AdminServer) handleRooms(w http.ResponseWriter, r *http.Request) { if srcRoom.Exits == nil { srcRoom.Exits = make(map[world.ExitDir]world.ExitDef) } - srcRoom.Exits[dir] = world.ExitDef{Room: id} + srcRoom.Exits[dir] = world.ExitDef{Room: id, Hidden: linkHidden, AlwaysBlocked: linkBlocked} srcPath, srcOk := s.world.GetRoomPath(*linkFrom) if srcOk { oldContent, _ := snapshotFile(srcPath) @@ -247,6 +301,8 @@ func (s *AdminServer) handleRoomByID(w http.ResponseWriter, r *http.Request) { return } + courseID, _ := s.detachRoomFromCourse(id) + if err := os.Remove(path); err != nil { writeJSON(w, map[string]any{"error": fmt.Sprintf("delete room: %v", err)}) return @@ -301,7 +357,11 @@ func (s *AdminServer) handleRoomByID(w http.ResponseWriter, r *http.Request) { ExtraFiles: extraFiles, }) - writeJSON(w, map[string]any{"ok": true}) + resp := map[string]any{"ok": true} + if courseID != "" { + resp["course_cleaned"] = courseID + } + writeJSON(w, resp) default: http.Error(w, `{"error":"method not allowed"}`, http.StatusMethodNotAllowed) @@ -424,10 +484,12 @@ func (s *AdminServer) handleRoomLink(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodPost: var body struct { - From int `json:"from"` - To int `json:"to"` - Dir string `json:"dir"` - OneWay bool `json:"oneway"` + From int `json:"from"` + To int `json:"to"` + Dir string `json:"dir"` + OneWay bool `json:"oneway"` + Hidden bool `json:"hidden"` + AlwaysBlocked bool `json:"always_blocked"` } if err := readJSON(r, &body); err != nil || body.From <= 0 || body.To <= 0 { writeJSONError(w, "invalid body, need from and to", http.StatusBadRequest) @@ -555,13 +617,13 @@ func (s *AdminServer) handleRoomLink(w http.ResponseWriter, r *http.Request) { if roomA.Exits == nil { roomA.Exits = make(map[world.ExitDir]world.ExitDef) } - roomA.Exits[dir] = world.ExitDef{Room: body.To} + roomA.Exits[dir] = world.ExitDef{Room: body.To, Hidden: body.Hidden, AlwaysBlocked: body.AlwaysBlocked} if !body.OneWay { if roomB.Exits == nil { roomB.Exits = make(map[world.ExitDir]world.ExitDef) } - roomB.Exits[oppDir] = world.ExitDef{Room: body.From} + roomB.Exits[oppDir] = world.ExitDef{Room: body.From, Hidden: body.Hidden, AlwaysBlocked: body.AlwaysBlocked} } pathA, okA2 := s.world.GetRoomPath(body.From) -- cgit v1.2.3