Class: Lich::Common::Map

Inherits:
Object
  • Object
show all
Includes:
Enumerable, MapBase
Defined in:
documented/common/map/map_dr.rb,
documented/common/map/map_gs.rb

Overview

GemStone-specific Map implementation Inherits shared functionality from MapBase Includes GS-specific features: get_location, peer tags, meta:map tags, player shops

Direct Known Subclasses

Room

Constant Summary collapse

PEER_TAG_PATTERN =

Pattern identifying a room whose disambiguation depends on a manual peer action (for example peering through a doorway to read an adjacent room before committing to a match). Such rooms cannot be told apart without a running script to perform the peer, so scriptless fuzzy matching declines to resolve them. Kept verbatim from the historical inline checks in match_fuzzy.

/^(set desc on; )?peer [a-z]+ =~ \/.+\/$/
@@loaded =
false
@@load_mutex =
Mutex.new
@@current_room_mutex =
Mutex.new
@@fuzzy_room_mutex =
Mutex.new
@@uids =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from MapBase

included

Constructor Details

#initialize(id, title, description, paths, uid = [], location = nil, climate = nil, terrain = nil, wayto = {}, timeto = {}, image = nil, image_coords = nil, tags = [], check_location = nil, unique_loot = nil) ⇒ Map

Initializes a Map room with all metadata.

Rooms are automatically registered in the class-level @@list and made available via .list, .[id], and iteration. If the map is already loaded, the tag index is reset to reflect the new room; during bulk load (when @@loaded is false), tag index resets are deferred until load_json finishes.

Parameters:

  • id (Integer)

    unique room identifier

  • title (Array<String>)

    room title(s); newest first

  • description (Array<String>)

    room description(s); newest first

  • paths (Array<String>)

    exit/path strings; newest first

  • uid (Array<Integer>) (defaults to: [])

    GemStone unique IDs; default []

  • location (String, nil) (defaults to: nil)

    in-game location from 'location' command; default nil

  • climate (String, nil) (defaults to: nil)

    climate tag; default nil

  • terrain (String, nil) (defaults to: nil)

    terrain tag; default nil

  • wayto (Hash) (defaults to: {})

    navigation hints (not currently used); default {}

  • timeto (Hash) (defaults to: {})

    travel time estimates (not currently used); default {}

  • image (String, nil) (defaults to: nil)

    map image file reference; default nil

  • image_coords (String, nil) (defaults to: nil)

    coordinates within the image; default nil

  • tags (Array<String>) (defaults to: [])

    searchable tags including special meta:map tags; default []

  • check_location (Boolean, nil) (defaults to: nil)

    when true, require location match during current room lookup; default nil

  • unique_loot (Array<String>, nil) (defaults to: nil)

    specific items that appear only in this room; default nil



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'documented/common/map/map_dr.rb', line 60

def initialize(id, title, description, paths, uid = [], location = nil,
               climate = nil, terrain = nil, wayto = {}, timeto = {},
               image = nil, image_coords = nil, tags = [], check_location = nil,
               unique_loot = nil, _room_objects = nil,
               genie_id = nil, genie_zone = nil, genie_pos = nil)
  @id = id
  @title = title
  @description = description
  @paths = paths
  @uid = uid
  @location = location
  @climate = climate
  @terrain = terrain
  @wayto = wayto
  @timeto = timeto
  @image = image
  @image_coords = image_coords
  @tags = TagList.new(tags, self.class)
  @check_location = check_location
  @unique_loot = unique_loot
  @genie_id = genie_id
  @genie_zone = genie_zone
  @genie_pos = genie_pos
  @@list[@id] = self
  # Skipped during a bulk load: @@loaded is false throughout, load_json
  # clears the cache when it finishes, and any tag query while unloaded
  # goes through #list, which loads first. Saves one mutex per room.
  self.class.reset_tag_index if @@loaded
end

Instance Attribute Details

#check_locationObject

Returns the value of attribute check_location.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def check_location
  @check_location
end

#climateObject

Returns the value of attribute climate.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def climate
  @climate
end

#descriptionObject

Returns the value of attribute description.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def description
  @description
end

#genie_idObject

Returns the value of attribute genie_id.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def genie_id
  @genie_id
end

#genie_posObject

Returns the value of attribute genie_pos.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def genie_pos
  @genie_pos
end

#genie_zoneObject

Returns the value of attribute genie_zone.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def genie_zone
  @genie_zone
end

#idObject (readonly)

Returns the value of attribute id.



29
30
31
# File 'documented/common/map/map_dr.rb', line 29

def id
  @id
end

#imageObject

Returns the value of attribute image.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def image
  @image
end

#image_coordsObject

Returns the value of attribute image_coords.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def image_coords
  @image_coords
end

#locationObject

Returns the value of attribute location.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def location
  @location
end

#pathsObject

Returns the value of attribute paths.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def paths
  @paths
end

#room_objectsObject

Returns the value of attribute room_objects.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def room_objects
  @room_objects
end

#tagsTagList (readonly)

Returns mutation-aware list of this room's tags.

Returns:

  • (TagList)

    mutation-aware list of this room's tags



36
37
38
# File 'documented/common/map/map_dr.rb', line 36

def tags
  @tags
end

#terrainObject

Returns the value of attribute terrain.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def terrain
  @terrain
end

#timetoObject

Returns the value of attribute timeto.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def timeto
  @timeto
end

#titleObject

Returns the value of attribute title.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def title
  @title
end

#uidObject

Returns the value of attribute uid.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def uid
  @uid
end

#unique_lootObject

Returns the value of attribute unique_loot.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def unique_loot
  @unique_loot
end

#waytoObject

Returns the value of attribute wayto.



30
31
32
# File 'documented/common/map/map_dr.rb', line 30

def wayto
  @wayto
end

Class Method Details

.by_genie_ref(zone_id, node_id) ⇒ Map?

Note:

Triggers .load if not yet loaded

Looks up a room by its genie (map client) zone and node identifiers.

Parameters:

  • zone_id (Integer, String)

    the genie zone identifier

  • node_id (Integer, String)

    the genie node identifier

Returns:

  • (Map, nil)

    the matched room, or nil if no room carries that genie reference



211
212
213
214
# File 'documented/common/map/map_dr.rb', line 211

def self.by_genie_ref(zone_id, node_id)
  self.load unless @@loaded
  @@list.find { |r| r&.genie_zone == zone_id.to_s && r&.genie_id == node_id.to_s }
end

.clearBoolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Clears the entire map from memory and resets the loaded state.

Acquires the load mutex before clearing to ensure thread safety. Also clears the tag cache, location cache, image cache, and triggers garbage collection.

Returns:

  • (Boolean)

    true



511
512
513
514
515
516
517
518
519
# File 'documented/common/map/map_dr.rb', line 511

def self.clear
  @@load_mutex.synchronize do
    @@list.clear
    clear_tags_cache
    @@loaded = false
    GC.start
  end
  true
end

.clear_tags_cachevoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Clears the cached tag index, forcing rebuild on next tag query.



183
184
185
# File 'documented/common/map/map_dr.rb', line 183

def clear_tags_cache
  reset_tag_index
end

.currentMap?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the Map room object for the current location, matching by UID, description, title, exits, and optional peer tags and location requirements.

Returns nil if the room cannot be matched. Caches the result per room_count to avoid redundant matching on the same server message. Uses UIDs as primary lookup, then falls back to multi-UID rooms and description matching.

This method is called automatically by the game loop and is not typically invoked directly from scripts.

Returns:

  • (Map, nil)

    the current room object, or nil if not identified

See Also:



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'documented/common/map/map_dr.rb', line 231

def self.current
  self.load unless @@loaded
  if Script.current
    return @@list[@@current_room_id] if XMLData.room_count == @@current_room_count && !@@current_room_id.nil?
  elsif XMLData.room_count == @@fuzzy_room_count && !@@current_room_id.nil?
    return @@list[@@current_room_id]
  end
  ids = XMLData.room_id.zero? ? [] : ids_from_uid(XMLData.room_id)
  return set_current(ids[0]) if ids.size == 1

  if ids.size > 1 && !@@current_room_id.nil? && (id = match_multi_ids(ids))
    return set_current(id)
  end
  match_no_uid
end

.current_or_newObject

GS-specific: Extended current_or_new with meta:map tag handling



420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
# File 'documented/common/map/map_dr.rb', line 420

def self.current_or_new
  return nil unless Script.current

  @@current_room_count = -1
  @@fuzzy_room_count = -1

  self.load unless @@loaded

  id = current&.id

  echo("Map: current room id is #{id.inspect}")
  unless id.nil?
    room = self[id]
    unless XMLData.room_id.zero? || room.uid.include?(XMLData.room_id)
      room.uid << XMLData.room_id
      uids_add(XMLData.room_id, room.id)
      echo "Map: Adding new uid for #{room.id}: #{XMLData.room_id}"
    end
    return set_current(room.id)
  end

  # Guard against a blank/incomplete arrival frame. DR occasionally streams a room whose
  # <nav> UID is delayed or absent (room_id 0) before the room text populates: the
  # description is only the "pitch dark" placeholder and there are no exits. Minting a
  # room here creates a junk stub (empty title, no UID) that orphans or duplicates the
  # real room. Keep the current room instead; the real room resolves by UID once the
  # delayed nav (or a re-look) provides it.
  if XMLData.room_id.zero? &&
     XMLData.room_exits_string.to_s.strip.empty? &&
     XMLData.room_description.to_s.strip == "It's pitch dark and you can't see a thing!"
    echo 'Map: skipped blank/incomplete room frame (no uid, pitch-dark, no exits)'
    # Keep the current room - but only if one has actually resolved.
    # @@current_room_id is the -1 sentinel before the first match; passing
    # that to set_current would index @@list[-1] (the last room) and make an
    # unrelated room current, so fall back to nil in that case instead.
    return set_current(@@current_room_id) if @@current_room_id.is_a?(Integer) && @@current_room_id >= 0

    return nil
  end

  id = get_free_id
  title = [XMLData.room_title]
  description = [XMLData.room_description.strip]
  paths = [XMLData.room_exits_string.strip]
  uid = XMLData.room_id.zero? ? [] : [XMLData.room_id]
  room = new(id, title, description, paths, uid)
  uids_add(XMLData.room_id, room.id) unless XMLData.room_id.zero?
  echo "mapped new room, set current room to #{room.id}"
  set_current(id)
end

.current_room_idInteger?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the room ID the current script is in, or nil if not yet set.

Returns:

  • (Integer, nil)

    the current room ID



110
111
112
# File 'documented/common/map/map_dr.rb', line 110

def current_room_id
  @@current_room_id
end

.current_room_id=(id) ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Sets the room ID for the current script.

Parameters:

  • id (Integer)

    room ID

Returns:

  • (Integer)

    the new room ID



119
120
121
# File 'documented/common/map/map_dr.rb', line 119

def current_room_id=(id)
  @@current_room_id = id
end

.fuzzy_room_idInteger?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the room ID of the last fuzzy match attempt, for scripts without current script context (used in background thread mode).

Returns:

  • (Integer, nil)

    the fuzzy-matched room ID



226
227
228
# File 'documented/common/map/map_gs.rb', line 226

def self.fuzzy_room_id
  @@fuzzy_room_id
end

.get_locationObject

GS-specific: Get location using in-game 'location' command



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'documented/common/map/map_gs.rb', line 231

def self.get_location
  unless XMLData.room_count == @@current_location_count
    if (script = Script.current)
      save_want_downstream = script.want_downstream
      script.want_downstream = true
      waitrt?
      location_result = dothistimeout(
        'location', 15,
        /^You carefully survey your surroundings and guess that your current location is .*? or somewhere close to it\.$|^You can't do that while submerged under water\.$|^You can't do that\.$|^It would be rude not to give your full attention to the performance\.$|^You can't do that while hanging around up here!$|^You are too distracted by the difficulty of staying alive in these treacherous waters to do that\.$|^You carefully survey your surroundings but are unable to guess your current location\.$|^Not in pitch darkness you don't\.$|^That is too difficult to consider here\.$/
      )
      script.want_downstream = save_want_downstream
      @@current_location_count = XMLData.room_count
      if location_result =~ /^You can't do that while submerged under water\.$|^You can't do that\.$|^It would be rude not to give your full attention to the performance\.$|^You can't do that while hanging around up here!$|^You are too distracted by the difficulty of staying alive in these treacherous waters to do that\.$|^You carefully survey your surroundings but are unable to guess your current location\.$|^Not in pitch darkness you don't\.$|^That is too difficult to consider here\.$/
        @@current_location = false
      else
        @@current_location = /^You carefully survey your surroundings and guess that your current location is (.*?) or somewhere close to it\.$/.match(location_result).captures.first
      end
    else
      return nil
    end
  end
  @@current_location
end

.ids_from_uid(n) ⇒ Array<Integer>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the room IDs associated with a GemStone UID, or empty array if not found.

Parameters:

  • n (Integer)

    GemStone UID from XMLData.room_id

Returns:

  • (Array<Integer>)

    matching room IDs; empty if UID not known



499
500
501
# File 'documented/common/map/map_dr.rb', line 499

def self.ids_from_uid(n)
  @@uids[n].nil? || n.zero? ? [] : @@uids[n]
end

.imagesObject

GS-specific: Get all unique map images



593
594
595
596
597
# File 'documented/common/map/map_gs.rb', line 593

def self.images
  self.load unless @@loaded
  @@images = @@list.compact.each_with_object({}) { |r, h| h[r.image] = nil unless h.key?(r.image) }.keys if @@images.empty?
  @@images.dup
end

.listArray<Map>

Returns the complete array of all loaded rooms, loading the map if needed.

Triggers a load on first call. Thread-safe. Safe to iterate while the map is being modified.

Examples:

Map.list.size #=> 12345
Map.list.first #=> #<Map id=1>

Returns:

  • (Array<Map>)

    all room objects



150
151
152
153
# File 'documented/common/map/map_dr.rb', line 150

def list
  self.load unless @@loaded
  @@list
end

.list=(value) ⇒ Array<Map>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Replaces the entire room list and normalizes tag lists for efficient searching.

Parameters:

  • value (Array<Map>)

    new list of rooms

Returns:

  • (Array<Map>)

    the new list



167
168
169
170
# File 'documented/common/map/map_dr.rb', line 167

def list=(value)
  @@list = value
  normalize_tag_lists(value)
end

.load_uidsvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Rebuilds the UID lookup table from the current room list.

Clears @@uids and re-indexes all UIDs from every room in @@list. Called after loading the map file to make UID lookups available.



479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
# File 'documented/common/map/map_dr.rb', line 479

def self.load_uids
  self.load unless @@loaded
  @@uids.clear
  # compact rather than relying on Lich's NilClass patch to make r.uid on a
  # hole return nil; a sparse map should not need that to load.
  @@list.compact.each do |r|
    r.uid.each do |u|
      if @@uids[u].nil?
        @@uids[u] = [r.id]
      elsif !@@uids[u].include?(r.id)
        @@uids[u] << r.id
      end
    end
  end
end

.loadedBoolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns whether the map has finished loading from the map file.

Returns:

  • (Boolean)

    true if the map is loaded



110
111
112
# File 'documented/common/map/map_gs.rb', line 110

def loaded
  @@loaded
end

.loaded?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns whether the map has finished loading from the map file.

Returns:

  • (Boolean)

    true if the map is loaded



142
143
144
# File 'documented/common/map/map_dr.rb', line 142

def loaded?
  @@loaded
end

.locationsObject

GS-specific: Get all unique locations



586
587
588
589
590
# File 'documented/common/map/map_gs.rb', line 586

def self.locations
  self.load unless @@loaded
  @@locations = @@list.compact.each_with_object({}) { |r, h| h[r.location] = nil unless h.key?(r.location) }.keys if @@locations.empty?
  @@locations.dup
end

.mark_loadedBoolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Marks the map as fully loaded.

Returns:

  • (Boolean)

    true



191
192
193
# File 'documented/common/map/map_dr.rb', line 191

def mark_loaded
  @@loaded = true
end

.match_current(script) ⇒ Object

GS-specific: match_current with peer tag checking



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
# File 'documented/common/map/map_dr.rb', line 315

def self.match_current(_script)
  @@current_room_mutex.synchronize do
    need_set_desc_off = false
    begin
      loop do
        @@current_room_count = XMLData.room_count
        foggy_exits = XMLData.room_exits_string =~ /^Obvious (?:exits|paths): obscured by a thick fog$/
        room = @@list.find do |r|
          # Skip nil holes without relying on Lich's NilClass patch.
          r &&
            r.title.include?(XMLData.room_title) &&
            r.description.include?(XMLData.room_description.strip) &&
            (foggy_exits || r.paths.include?(XMLData.room_exits_string.strip))
        end

        if room
          redo unless @@current_room_count == XMLData.room_count
          return resolve_matched_room(room, honor_peer_tags: false)
        else
          redo unless @@current_room_count == XMLData.room_count
          desc_regex = /#{Regexp.escape(XMLData.room_description.strip.sub(/\.+$/, '')).gsub(/\\\.(?:\\\.\\\.)?/, '|')}/
          room = @@list.find do |r|
            # Skip nil holes without relying on Lich's NilClass patch.
            r &&
              r.title.include?(XMLData.room_title) &&
              (foggy_exits || r.paths.include?(XMLData.room_exits_string.strip)) &&
              (XMLData.room_window_disabled || r.description.any? { |desc| desc =~ desc_regex })
          end

          if room
            redo unless @@current_room_count == XMLData.room_count
            return resolve_matched_room(room, honor_peer_tags: false)
          else
            redo unless @@current_room_count == XMLData.room_count
            return nil
          end
        end
      end
    ensure
      put 'set description off' if need_set_desc_off
    end
  end
end

.match_fuzzyInteger?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Matches the current location to a room, used in non-script contexts where peer tags cannot be checked.

Used by background threads and front-end clients that do not have script context. Skips peer tag matching because those tags require executing in-game commands that only a script can do safely. Returns nil if the room has unresolved peer tag requirements.

Returns:

  • (Integer, nil)

    the matched room ID, or nil if no match or match has peer tags



369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'documented/common/map/map_dr.rb', line 369

def self.match_fuzzy
  @@fuzzy_room_mutex.synchronize do
    @@fuzzy_room_count = XMLData.room_count
    loop do
      foggy_exits = XMLData.room_exits_string =~ /^Obvious (?:exits|paths): obscured by a thick fog$/
      room = @@list.find do |r|
        # Skip nil holes without relying on Lich's NilClass patch.
        r &&
          r.title.include?(XMLData.room_title) &&
          r.description.include?(XMLData.room_description.strip) &&
          (foggy_exits || r.paths.include?(XMLData.room_exits_string.strip))
      end

      if room
        redo unless @@fuzzy_room_count == XMLData.room_count

        return resolve_matched_room(room, honor_peer_tags: true)
      else
        redo unless @@fuzzy_room_count == XMLData.room_count
        desc_regex = /#{Regexp.escape(XMLData.room_description.strip.sub(/\.+$/, '')).gsub(/\\\.(?:\\\.\\\.)?/, '|')}/
        room = @@list.find do |r|
          # Skip nil holes without relying on Lich's NilClass patch.
          r &&
            r.title.include?(XMLData.room_title) &&
            (foggy_exits || r.paths.include?(XMLData.room_exits_string.strip)) &&
            (XMLData.room_window_disabled || r.description.any? { |desc| desc =~ desc_regex })
        end

        if room
          redo unless @@fuzzy_room_count == XMLData.room_count

          return resolve_matched_room(room, honor_peer_tags: true)
        else
          redo unless @@fuzzy_room_count == XMLData.room_count
          return nil
        end
      end
    end
  end
end

.peer_disambiguation_tag?(room) ⇒ Boolean

Whether room carries a peer-disambiguation tag (see PEER_TAG_PATTERN).

Parameters:

Returns:

  • (Boolean)

    true when the room requires a manual peer to disambiguate, false otherwise



261
262
263
# File 'documented/common/map/map_dr.rb', line 261

def self.peer_disambiguation_tag?(room)
  room.tags.any? { |tag| tag =~ PEER_TAG_PATTERN }
end

.previousMap?

Returns the Map room object for the previous location, or nil if not yet set.

Examples:

Map.previous #=> #<Map id=1234>
Map.previous #=> nil  # if no previous room recorded

Returns:

  • (Map, nil)

    the previous room



219
220
221
# File 'documented/common/map/map_dr.rb', line 219

def self.previous
  @@list[@@previous_room_id]
end

.previous_room_idInteger?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the room ID the current script was previously in, or nil if not yet set.

Returns:

  • (Integer, nil)

    the previous room ID



126
127
128
# File 'documented/common/map/map_dr.rb', line 126

def previous_room_id
  @@previous_room_id
end

.previous_room_id=(id) ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Sets the room ID for the previous location.

Parameters:

  • id (Integer)

    room ID

Returns:

  • (Integer)

    the new room ID



135
136
137
# File 'documented/common/map/map_dr.rb', line 135

def previous_room_id=(id)
  @@previous_room_id = id
end

.raw_listObject

The backing array without triggering a load. Only for use inside the load path, where #list would re-enter the load mutex and deadlock.



157
158
159
# File 'documented/common/map/map_dr.rb', line 157

def raw_list
  @@list
end

.resolve_matched_room(room, honor_peer_tags:) ⇒ Integer?

Resolve a room that already matched on title/description/paths down to a final room id, applying UID disambiguation.

The governing invariant is that a stored UID must never make a room less resolvable than an otherwise identical room with no UID.

  • When the game exposes a live UID (+XMLData.room_id+ is non-zero) and the matched room carries one or more UIDs, the match only stands if the live UID is among them. This is what keeps distinct rooms that share a title/description/paths (day/night variants, look-alike maze cells) from collapsing onto one another.
  • When the game exposes no UID (+XMLData.room_id+ is zero, a room the server does not surface a UID for), UID disambiguation is skipped and the title/description/paths match is trusted regardless of any UID stored on the room. Previously such a room returned nil here (a stored UID can never include the zero live id), so a UID accidentally or provisionally stamped onto a no-UID room made that room permanently unresolvable (+Map.current+ became nil). Trusting the text match in the no-UID case removes that failure mode without weakening disambiguation when the game does expose a UID.

Parameters:

  • room (Lich::Common::Map)

    the room matched on title/description/paths

  • honor_peer_tags (Boolean)

    when true, a room requiring a manual peer to disambiguate (see peer_disambiguation_tag?) resolves to nil; used by scriptless fuzzy matching, which cannot perform the peer. Exact (match_current) matching passes false and never consults peer tags.

Returns:

  • (Integer, nil)

    the resolved room id; nil when a UID'd room's stored UIDs exclude the live game UID, or when a peer-tagged room cannot be disambiguated



294
295
296
297
298
299
300
301
# File 'documented/common/map/map_dr.rb', line 294

def self.resolve_matched_room(room, honor_peer_tags:)
  if room.uid.any? && !XMLData.room_id.zero?
    return room.uid.include?(XMLData.room_id) ? room.id : nil
  end
  return nil if honor_peer_tags && peer_disambiguation_tag?(room)

  room.id
end

.room_from_json(room) ⇒ Map

Construct a room from a parsed JSON hash

Parameters:

Returns:

  • (Map)

    the registered room



524
525
526
527
528
529
530
531
532
533
# File 'documented/common/map/map_dr.rb', line 524

def self.room_from_json(room)
  new(
    room['id'], room['title'], room['description'], room['paths'],
    room['uid'], room['location'], room['climate'], room['terrain'],
    room['wayto'], room['timeto'], room['image'], room['image_coords'],
    room['tags'], room['check_location'], room['unique_loot'],
    nil, # _room_objects
    room['genie_id'], room['genie_zone'], room['genie_pos']
  )
end

.synchronize_load { ... } ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Executes a block under the map load mutex to ensure thread-safe loading.

Yields:

  • runs the given block with the load lock held

Returns:

  • (Object)

    the result of the block



200
201
202
# File 'documented/common/map/map_dr.rb', line 200

def synchronize_load(&block)
  @@load_mutex.synchronize(&block)
end

.uidsHash{Integer => Array<Integer>}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the GemStone UID-to-room-IDs lookup table.

Returns:

  • (Hash{Integer => Array<Integer>})

    maps UID to array of room IDs



175
176
177
# File 'documented/common/map/map_dr.rb', line 175

def uids
  @@uids
end

.uids_clearvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Clears the UID-to-room-ID lookup table.



603
604
605
# File 'documented/common/map/map_gs.rb', line 603

def self.uids_clear
  @@uids.clear
end

Instance Method Details

#fuzzy_room_idInteger?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Note:

Prefer .current over this method.

Returns the current room ID (instance method alias for class variable).

Returns:

  • (Integer, nil)

    the current room ID



208
209
210
# File 'documented/common/map/map_gs.rb', line 208

def fuzzy_room_id
  @@current_room_id
end

#json_extra_fieldsHash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns extra genie-reference fields for JSON serialization.

Returns:

  • (Hash)

    genie-related metadata: genie_id, genie_zone, genie_pos



101
102
103
# File 'documented/common/map/map_dr.rb', line 101

def json_extra_fields
  { genie_id: @genie_id, genie_zone: @genie_zone, genie_pos: @genie_pos }
end

#to_sString

Returns a human-readable string representation of this room.

Examples:

room.to_s #=> "#1234 (u4294967295):\nRoad (Wehnimer's Landing)\nA dusty road...\nObvious exits: north, south"

Returns:

  • (String)

    room ID, newest UID, title, location, description, and exits



93
94
95
# File 'documented/common/map/map_dr.rb', line 93

def to_s
  "##{@id} (#{@uid[-1]}):\n#{@title[-1]}\n#{@description[-1]}\n#{@paths[-1]}"
end