aboutsummaryrefslogtreecommitdiff
path: root/internal/admin
diff options
context:
space:
mode:
Diffstat (limited to 'internal/admin')
-rw-r--r--internal/admin/api_map.go6
-rw-r--r--internal/admin/api_rooms.go5
-rw-r--r--internal/admin/api_rooms_bulk.go5
-rw-r--r--internal/admin/server.go8
4 files changed, 23 insertions, 1 deletions
diff --git a/internal/admin/api_map.go b/internal/admin/api_map.go
index d0372df..231f52b 100644
--- a/internal/admin/api_map.go
+++ b/internal/admin/api_map.go
@@ -246,6 +246,10 @@ func (s *AdminServer) handleMap(w http.ResponseWriter, r *http.Request) {
var upLinks []UDLink
var downLinks []UDLink
+ // Hoist the room index once: RoomIndex builds a fresh map copy under the
+ // world lock, and calling it per exit made this loop O(rooms x exits x
+ // rooms) with a mutex acquisition each time.
+ roomIndex := s.world.RoomIndex()
seenLinks := make(map[string]bool)
for rid, room := range roomData {
c := g.Coord[rid]
@@ -255,7 +259,7 @@ func (s *AdminServer) handleMap(w http.ResponseWriter, r *http.Request) {
continue
}
targetCoord, hasCoord := g.Coord[target]
- targetExists := s.world.RoomIndex()[target]
+ _, targetExists := roomIndex[target]
if !targetExists || !hasCoord {
if dir != world.Up && dir != world.Down {
diff --git a/internal/admin/api_rooms.go b/internal/admin/api_rooms.go
index 863af47..ca7ad06 100644
--- a/internal/admin/api_rooms.go
+++ b/internal/admin/api_rooms.go
@@ -311,6 +311,11 @@ func (s *AdminServer) handleRoomByID(w http.ResponseWriter, r *http.Request) {
failJSON(w, fmt.Sprintf("write room: %v", err))
return
}
+ // Refresh live runtime state (objects, spawns, mobs) so the edit takes
+ // effect without a restart; player-dropped items are preserved.
+ if s.reconcileRoom != nil {
+ s.reconcileRoom(id)
+ }
s.undoStack.Push(ChangeDesc{
Description: fmt.Sprintf("update room %d", id),
diff --git a/internal/admin/api_rooms_bulk.go b/internal/admin/api_rooms_bulk.go
index b9cbb4a..3296375 100644
--- a/internal/admin/api_rooms_bulk.go
+++ b/internal/admin/api_rooms_bulk.go
@@ -162,6 +162,11 @@ func (s *AdminServer) handleBulkEdit(w http.ResponseWriter, r *http.Request) {
}
s.world.RebuildRoomIndex(s.dataDir)
+ if s.reconcileRoom != nil {
+ for _, wr := range writes {
+ s.reconcileRoom(wr.id)
+ }
+ }
var desc string
if patch.Dir != nil && *patch.Dir != "" {
diff --git a/internal/admin/server.go b/internal/admin/server.go
index 4cceadd..9c62249 100644
--- a/internal/admin/server.go
+++ b/internal/admin/server.go
@@ -73,6 +73,12 @@ type AdminServer struct {
// wired game callback before the cache entries drop.
evictRoom func(roomID int)
+ // reconcileRoom refreshes a room's live runtime state (object instances,
+ // item-spawn entries, mob instances) from its edited definition, so a
+ // content edit takes effect without a restart. Wired from the Game, which
+ // owns MobStore; optional (nil in tests).
+ reconcileRoom func(roomID int)
+
// rebuildCraftIndex rebuilds the in-game craft index after item files
// change (create/update/delete/rename/move/undo/redo). Wired from the
// Game so the web editor's item edits stay consistent with gameplay.
@@ -107,6 +113,7 @@ type ServerDeps struct {
ReloadCourses func()
RewriteRoomIDs func(map[int]int)
EvictRoom func(roomID int)
+ ReconcileRoom func(roomID int)
RebuildCraftIndex func()
ConfigPath string
RunOnOwner func(func()) bool
@@ -161,6 +168,7 @@ func NewServer(deps ServerDeps) (*AdminServer, error) {
reloadCourses: deps.ReloadCourses,
rewriteRoomIDs: deps.RewriteRoomIDs,
evictRoom: deps.EvictRoom,
+ reconcileRoom: deps.ReconcileRoom,
rebuildCraftIndex: deps.RebuildCraftIndex,
configPath: deps.ConfigPath,
runOnOwner: deps.RunOnOwner,