diff --git a/internal/mapper/mapper.go b/internal/mapper/mapper.go index 60c63503..4795c133 100644 --- a/internal/mapper/mapper.go +++ b/internal/mapper/mapper.go @@ -4,7 +4,7 @@ import ( "errors" "fmt" "math" - "sort" + "strconv" "strings" "time" "unicode" @@ -97,7 +97,8 @@ var ( "southeast-gap3": {3, 3, 0, ' '}, } - mapperZoneCache = map[string]*mapper{} + mapperZoneCache = map[string]*mapper{} // zonename-{"random" roomId} to mapper + roomIdToMapperCache = map[int]string{} // roomId to mapperZoneCache key ) func GetDelta(exitName string) (x, y, z int) { @@ -125,46 +126,6 @@ func IsValidDirection(directionName string) bool { return ok } -func GetZoneMapper(zoneName string, forceRefresh ...bool) *mapper { - - doRefresh := len(forceRefresh) > 0 && forceRefresh[0] - - if !doRefresh { - if _, ok := mapperZoneCache[zoneName]; ok { - return mapperZoneCache[zoneName] - } - } - - roomId, err := rooms.GetZoneRoot(zoneName) - if err != nil { - return nil - } - - for zName, mapper := range mapperZoneCache { - if mapper.HasRoom(roomId) { - - if doRefresh { - delete(mapperZoneCache, zName) - zoneName = zName - } else { - return mapper - } - } - } - - // not found. Will need to create one. - tStart := time.Now() - - m := NewMapper(roomId) - m.Start() - - mudlog.Info("New Mapper", "zone", zoneName, "time taken", time.Since(tStart)) - - mapperZoneCache[zoneName] = m - - return m -} - type positionDelta struct { x int y int @@ -239,6 +200,14 @@ type crawlRoom struct { Pos positionDelta // Its x/y/z position relative to the root node } +func (r *mapper) CrawledRoomIds() []int { + roomIds := []int{} + for roomId := range r.crawledRooms { + roomIds = append(roomIds, roomId) + } + return roomIds +} + func (r *mapper) Start() { // Don't redo. @@ -846,31 +815,48 @@ func (r *mapper) getMapNode(roomId int) *mapNode { return mNode } -func PreCacheMaps() { +func GetMapper(roomId int, forceRefresh ...bool) *mapper { + + // Check the room-to-cache lookup + if zoneName, ok := roomIdToMapperCache[roomId]; ok { + return mapperZoneCache[zoneName] + } + + zoneName := `` + if room := rooms.LoadRoom(roomId); room != nil { + zoneName = room.Zone + zoneName += `-` + strconv.Itoa(roomId) + } + + // not found. Will need to create one. + tStart := time.Now() + + m := NewMapper(roomId) + m.Start() + + mudlog.Info("New Mapper", "zone", zoneName, "time taken", time.Since(tStart)) + + roomIdToMapperCache[roomId] = zoneName - // Sort the rooms by roomId before precaching. - // This ensures a somewhat predictable inferred coordinate system across - // MUD server starts. - type ZoneDetails struct { - Name string - RootRoomId int + for _, crawledRoomId := range m.CrawledRoomIds() { + if _, ok := roomIdToMapperCache[crawledRoomId]; !ok { + roomIdToMapperCache[crawledRoomId] = zoneName + } } - allZones := []ZoneDetails{} + mapperZoneCache[zoneName] = m + + return m +} + +func PreCacheMaps() { for _, name := range rooms.GetAllZoneNames() { rootRoomId, _ := rooms.GetZoneRoot(name) - allZones = append(allZones, ZoneDetails{ - Name: name, - RootRoomId: rootRoomId, - }) + GetMapper(rootRoomId) } - sort.Slice(allZones, func(i, j int) bool { - return allZones[i].RootRoomId < allZones[j].RootRoomId - }) - - for _, zInfo := range allZones { - GetZoneMapper(zInfo.Name) + for _, roomId := range rooms.GetAllRoomIds() { + GetMapper(roomId) } } diff --git a/internal/mapper/mapper.path.go b/internal/mapper/mapper.path.go index 7a5e7f4f..a95923aa 100644 --- a/internal/mapper/mapper.path.go +++ b/internal/mapper/mapper.path.go @@ -209,7 +209,7 @@ func GetPath(startRoomId int, endRoomId ...int) ([]pathStep, error) { return []pathStep{}, fmt.Errorf("%d => %d (startRoom not found): %w", startRoomId, endRoomId, ErrPathNotFound) } - m := GetZoneMapper(startRoom.Zone) + m := GetMapper(startRoom.RoomId) if m == nil { return []pathStep{}, fmt.Errorf("%d => %d (mapper not fond): %w", startRoomId, endRoomId, ErrPathNotFound) } diff --git a/internal/rooms/roommanager.go b/internal/rooms/roommanager.go index f69c9767..9ebf34c5 100644 --- a/internal/rooms/roommanager.go +++ b/internal/rooms/roommanager.go @@ -181,6 +181,21 @@ func GetAllZoneNames() []string { return zoneNames } +func GetAllZoneRoomsIds(zoneName string) []int { + + if zoneInfo, ok := roomManager.zones[zoneName]; ok { + result := make([]int, len(zoneInfo.RoomIds)) + idx := 0 + for roomId, _ := range zoneInfo.RoomIds { + result[idx] = roomId + idx++ + } + return result + } + + return []int{} +} + func MoveToRoom(userId int, toRoomId int, isSpawn ...bool) error { user := users.GetByUserId(userId) diff --git a/internal/scripting/room_func.go b/internal/scripting/room_func.go index 791c6131..ac8c6a86 100644 --- a/internal/scripting/room_func.go +++ b/internal/scripting/room_func.go @@ -340,10 +340,10 @@ func GetMap(mapRoomId int, zoomLevel int, mapHeight int, mapWidth int, mapName s return "" } - zMapper := mapper.GetZoneMapper(room.Zone) - if zMapper == nil { - mudlog.Error("Map", "error", "Could not find mapper for zone:"+room.Zone) - return "Could not find mapper for zone:" + room.Zone + rMapper := mapper.GetMapper(room.RoomId) + if rMapper == nil { + mudlog.Error("Map", "error", "Could not find mapper for roomId:"+strconv.Itoa(room.RoomId)) + return "Could not find mapper for roomId:" + strconv.Itoa(room.RoomId) } c := mapper.Config{ @@ -371,7 +371,7 @@ func GetMap(mapRoomId int, zoomLevel int, mapHeight int, mapWidth int, mapName s } } - mapOutput := zMapper.GetLimitedMap(mapRoomId, c) + mapOutput := rMapper.GetLimitedMap(mapRoomId, c) legend := mapOutput.GetLegend(keywords.GetAllLegendAliases(room.Zone)) diff --git a/internal/usercommands/admin.build.go b/internal/usercommands/admin.build.go index d206ab95..8604e5fc 100644 --- a/internal/usercommands/admin.build.go +++ b/internal/usercommands/admin.build.go @@ -67,15 +67,15 @@ func Build(rest string, user *users.UserRecord, room *rooms.Room, flags events.E var destinationRoom *rooms.Room = nil // If it's a compass direction, reject it if a room already exists in that direction - zMapper := mapper.GetZoneMapper(room.Zone) - if zMapper == nil { - err := fmt.Errorf("Could not find mapper for zone: %s", room.Zone) + rMapper := mapper.GetMapper(room.RoomId) + if rMapper == nil { + err := fmt.Errorf("Could not find mapper for roomId: %d", room.RoomId) mudlog.Error("Map", "error", err) user.SendText(`No map found (or an error occured)"`) return true, err } - if gotoRoomId, _ := zMapper.FindAdjacentRoom(user.Character.RoomId, exitName, 1); gotoRoomId == 0 { + if gotoRoomId, _ := rMapper.FindAdjacentRoom(user.Character.RoomId, exitName, 1); gotoRoomId == 0 { if newRoom, err := rooms.BuildRoom(user.Character.RoomId, exitName, mapDirection); err != nil { user.SendText(err.Error()) diff --git a/internal/usercommands/admin.teleport.go b/internal/usercommands/admin.teleport.go index 1b2bf383..60d39a07 100644 --- a/internal/usercommands/admin.teleport.go +++ b/internal/usercommands/admin.teleport.go @@ -43,7 +43,7 @@ func Teleport(rest string, user *users.UserRecord, room *rooms.Room, flags event return true, nil } - zMapper := mapper.GetZoneMapper(room.Zone) + zMapper := mapper.GetMapper(room.RoomId) if zMapper == nil { err := fmt.Errorf("Could not find mapper for zone: %s", room.Zone) mudlog.Error("Map", "error", err) diff --git a/internal/usercommands/look.go b/internal/usercommands/look.go index 0002d8da..521045b6 100644 --- a/internal/usercommands/look.go +++ b/internal/usercommands/look.go @@ -465,7 +465,7 @@ func lookRoom(user *users.UserRecord, roomId int, secretLook bool) { if tinyMapOn.(bool) && roomId > 0 { - zMapper := mapper.GetZoneMapper(room.Zone) + zMapper := mapper.GetMapper(room.RoomId) if zMapper == nil { mudlog.Error("Map", "error", "Could not find mapper for zone:"+room.Zone) diff --git a/internal/usercommands/skill.map.go b/internal/usercommands/skill.map.go index 5673e2dd..b123dc33 100644 --- a/internal/usercommands/skill.map.go +++ b/internal/usercommands/skill.map.go @@ -110,7 +110,7 @@ func Map(rest string, user *users.UserRecord, room *rooms.Room, flags events.Eve } - zMapper := mapper.GetZoneMapper(zone) + zMapper := mapper.GetMapper(roomId) if zMapper == nil { mudlog.Error("Map", "error", "Could not find mapper for zone:"+zone) user.SendText(`No map found (or an error occured)"`) diff --git a/modules/gmcp/gmcp.Room.go b/modules/gmcp/gmcp.Room.go index 637b267d..a45d7458 100644 --- a/modules/gmcp/gmcp.Room.go +++ b/modules/gmcp/gmcp.Room.go @@ -357,7 +357,7 @@ func (g *GMCPRoomModule) GetRoomNode(user *users.UserRecord, gmcpModule string) // Coordinates payload.Coordinates = room.Zone - m := mapper.GetZoneMapper(room.Zone) + m := mapper.GetMapper(room.RoomId) x, y, z, err := m.GetCoordinates(room.RoomId) if err != nil { payload.Coordinates += `, 999999999999999999, 999999999999999999, 999999999999999999`