From bab5dd653039d026eb3d4e46da7aafef7137fe7c Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Sat, 19 Sep 2026 03:52:04 -0400 Subject: fix: journal in-game room insert/remove, rewrite non-room room refs on rename/swap, seed admin grid from edited room, type action switches --- internal/game/cmd_room_remove.go | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'internal/game/cmd_room_remove.go') diff --git a/internal/game/cmd_room_remove.go b/internal/game/cmd_room_remove.go index 361cc74..79b84d8 100644 --- a/internal/game/cmd_room_remove.go +++ b/internal/game/cmd_room_remove.go @@ -166,15 +166,21 @@ func (g *Game) roomRemove(sess *net.Session, args []string) { return } - // Apply: rewire A's dir exit to C, preserving A's current dir-exit props. + // Stage A, C, and B's deletion into ONE journal transaction: the previous + // sequential writes could delete B after rewriting A but before C, leaving + // the map half-pulled with no recovery record. The transaction restores + // every before-image on any failure or crash. + txn := g.newTxn() + + // Rewire A's dir exit to C, preserving A's current dir-exit props. aRoom.Exits[dir] = world.RewirePreserving(aExit, cID) aData, err := yaml.Marshal(aRoom) if err != nil { sess.WriteLine("Error updating current room YAML.") return } - if err := writeRoomFile(aPath, aData); err != nil { - sess.WriteLine("Error writing current room file.") + if err := txn.Replace(aPath, aData, 0644); err != nil { + sess.WriteLine(fmt.Sprintf("Error writing current room file: %v", err)) return } @@ -183,21 +189,28 @@ func (g *Game) roomRemove(sess *net.Session, args []string) { cPath, cPathOK := g.World.GetRoomPath(cID) if cPathOK { cData, cerr := yaml.Marshal(cRoom) - if cerr == nil { - if werr := writeRoomFile(cPath, cData); werr != nil { - sess.WriteLine(fmt.Sprintf("Warning: could not link the opposite exit in room %d: %v", cID, werr)) - } + if cerr != nil { + sess.WriteLine(fmt.Sprintf("Error updating room %d YAML: %v", cID, cerr)) + return + } + if err := txn.Replace(cPath, cData, 0644); err != nil { + sess.WriteLine(fmt.Sprintf("Error linking the opposite exit in room %d: %v", cID, err)) + return } } - // Delete B's file. + // Delete B's file in the same transaction. bPath, bPathOK := g.World.GetRoomPath(bID) if !bPathOK { sess.WriteLine(fmt.Sprintf("Room file for %d not found.", bID)) return } - if rerr := os.Remove(bPath); rerr != nil { - sess.WriteLine(fmt.Sprintf("Error deleting room file: %v", rerr)) + if err := txn.Delete(bPath); err != nil { + sess.WriteLine(fmt.Sprintf("Error deleting room file: %v", err)) + return + } + if err := txn.Commit(); err != nil { + sess.WriteLine(fmt.Sprintf("Error committing room remove: %v", err)) return } -- cgit v1.2.3