Class: Lich::Common::Inventory::Snapshot

Inherits:
Object
  • Object
show all
Defined in:
documented/common/inventory.rb

Overview

An immutable, point-in-time inventory snapshot. Returned by refresh so a caller has a consistent view even as passive absorption swaps the global snapshot. Query it directly rather than re-reading the global accessors.

Immutability contract

The Snapshot, its id-keyed item map, its #room_id, and its worn/room/at-feet collections are frozen; each Item's identity strings, Item#flags, and Item#children are frozen too, so a consumer cannot corrupt shared state through a returned object (e.g. item.flags << "locked" raises). The Item objects themselves are deliberately NOT frozen: their backing GameObj is populated lazily for classification (see Item#register_gameobj), which would be impossible on a frozen instance. Treat every field as read-only regardless.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(items:, room_id:) ⇒ Snapshot

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 a new instance of Snapshot.

Parameters:

  • items (Hash{String => Item}) —

    id-keyed items (wire order)

  • room_id (String, nil) —

    envelope room id



541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'documented/common/inventory.rb', line 541

def initialize(items:, room_id:)
  @items      = items.freeze
  # Duplicated and frozen so shared snapshot metadata cannot be mutated
  # through {#room_id} (e.g. +Inventory.current.room_id.replace('x')+): the
  # room id arrives as an unfrozen Ox attribute string, unlike the {Item}
  # identity fields which are frozen at construction.
  @room_id    = room_id.nil? ? nil : room_id.dup.freeze
  @worn       = items.values.select(&:worn?).freeze
  @room       = items.values.select(&:in_room?).freeze
  @at_feet    = items.values.select(&:at_feet?).freeze
  @right_hand = items.values.find(&:in_right_hand?)
  @left_hand  = items.values.find(&:in_left_hand?)
  @built_at   = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  @last_updated = Time.now
  freeze
end

Instance Attribute Details

#last_updated ⇒ Time (readonly)

Returns wall-clock time the snapshot was built.

Returns:

  • (Time) —

    wall-clock time the snapshot was built



533
534
535
# File 'documented/common/inventory.rb', line 533

def last_updated
  @last_updated
end

#room_id ⇒ String? (readonly)

Returns the room id from the response envelope.

Returns:

  • (String, nil) —

    the room id from the response envelope



536
537
538
# File 'documented/common/inventory.rb', line 536

def room_id
  @room_id
end

Instance Method Details

#[](id) ⇒ Item?

Looks up an item by exist id.

Examples:

Inventory.refresh['40236126']

Parameters:

  • id (String, Integer) —

    the exist id

Returns:



569
570
571
# File 'documented/common/inventory.rb', line 569

def [](id)
  @items[id.to_s]
end

#age ⇒ Float

Seconds elapsed since the snapshot was built (monotonic).

Examples:

Inventory.refresh.age #=> 0.0

Returns:

  • (Float)


643
644
645
# File 'documented/common/inventory.rb', line 643

def age
  Process.clock_gettime(Process::CLOCK_MONOTONIC) - @built_at
end

#all ⇒ Array<Item>

Returns every item in the snapshot.

Returns:

  • (Array<Item>) —

    every item in the snapshot



559
560
561
# File 'documented/common/inventory.rb', line 559

def all
  @items.values
end

#at_feet ⇒ Array<Item>

Returns items on the ground at the player's feet.

Returns:

  • (Array<Item>) —

    items on the ground at the player's feet



619
620
621
# File 'documented/common/inventory.rb', line 619

def at_feet
  @at_feet
end

#containers ⇒ Array<Item>

Returns every item that is a container.

Returns:

  • (Array<Item>) —

    every item that is a container



599
600
601
# File 'documented/common/inventory.rb', line 599

def containers
  all.select(&:container?)
end

#find(pattern) ⇒ Item?

Finds the first item whose noun, name, or long matches.

Examples:

Inventory.refresh.find('lootpouch')

Parameters:

  • pattern (String, Regexp) —

    substring (case-insensitive) or regexp

Returns:



579
580
581
582
# File 'documented/common/inventory.rb', line 579

def find(pattern)
  rx = pattern.is_a?(Regexp) ? pattern : Regexp.new(Regexp.escape(pattern.to_s), Regexp::IGNORECASE)
  all.find { |item| item.noun =~ rx || item.name =~ rx || (item.long && item.long =~ rx) }
end

#left_hand ⇒ Item?

Returns the item in the player's left hand.

Returns:

  • (Item, nil) —

    the item in the player's left hand



614
615
616
# File 'documented/common/inventory.rb', line 614

def left_hand
  @left_hand
end

#right_hand ⇒ Item?

Returns the item in the player's right hand.

Returns:

  • (Item, nil) —

    the item in the player's right hand



609
610
611
# File 'documented/common/inventory.rb', line 609

def right_hand
  @right_hand
end

#room ⇒ Array<Item>

Returns items on the ground in the room (shared room loot, not necessarily the player's -- the feed lists every observer's droppings).

Returns:

  • (Array<Item>) —

    items on the ground in the room (shared room loot, not necessarily the player's -- the feed lists every observer's droppings)



625
626
627
# File 'documented/common/inventory.rb', line 625

def room
  @room
end

#total_weight ⇒ Integer

Total carried encumbrance in pounds: the recursive Item#total_weight (with the in_encum short-circuit) of everything worn AND held. Ground items (#room/#at_feet) are excluded -- they are not carried.

Returns:

  • (Integer)


634
635
636
# File 'documented/common/inventory.rb', line 634

def total_weight
  (@worn + [@right_hand, @left_hand].compact).sum(&:total_weight)
end

#where(noun: nil, name: nil) ⇒ Array<Item>

Filters items by exact noun and/or exact display name.

Examples:

Inventory.refresh.where(noun: 'ring')

Parameters:

  • noun (String, nil) (defaults to: nil) —

    exact noun to match

  • name (String, nil) (defaults to: nil) —

    exact display name to match

Returns:



591
592
593
594
595
596
# File 'documented/common/inventory.rb', line 591

def where(noun: nil, name: nil)
  result = all
  result = result.select { |item| item.noun == noun } if noun
  result = result.select { |item| item.name == name } if name
  result
end

#worn ⇒ Array<Item>

Returns items worn on the player.

Returns:

  • (Array<Item>) —

    items worn on the player



604
605
606
# File 'documented/common/inventory.rb', line 604

def worn
  @worn
end