Module: Lich::Common::CreatureBase::ClassMethods

Defined in:
documented/common/creature/creature_base.rb

Overview

Class-level behaviour: the id-keyed instance registry, the current-room roster and the target/room queries shared by both games' Creature facades.

State lives in per-class instance variables (@instances, @current_room_ids, ...), so each extending class keeps an independent registry - GemStone and DragonRealms never share a roster even though they share this code.

Instance Method Summary collapse

Instance Method Details

#[](id) ⇒ Object?

Looks up a registered instance by id.

Parameters:

  • id (Integer, String) —

    server creature id.

Returns:

  • (Object, nil)


273
274
275
# File 'documented/common/creature/creature_base.rb', line 273

def [](id)
  instances[id.to_i]
end

#all ⇒ Array<Object>

Returns every registered instance.

Returns:

  • (Array<Object>) —

    every registered instance.



278
279
280
# File 'documented/common/creature/creature_base.rb', line 278

def all
  instances.values
end

#auto_register? ⇒ Boolean

Returns whether auto-registration is enabled (default true).

Returns:

  • (Boolean) —

    whether auto-registration is enabled (default true).



317
318
319
320
# File 'documented/common/creature/creature_base.rb', line 317

def auto_register?
  @auto_register = true if @auto_register.nil?
  @auto_register
end

#cleanup_old(max_age_seconds = 600) ⇒ Integer

Removes instances older than the given age.

Parameters:

  • max_age_seconds (Integer) (defaults to: 600) —

    age cutoff in seconds.

Returns:

  • (Integer) —

    number of instances removed.



294
295
296
297
298
299
# File 'documented/common/creature/creature_base.rb', line 294

def cleanup_old(max_age_seconds = 600)
  cutoff = Time.now - max_age_seconds
  removed = instances.select { |_id, instance| instance.created_at < cutoff }.size
  instances.reject! { |_id, instance| instance.created_at < cutoff }
  removed
end

#clear ⇒ void

This method returns an undefined value.

Clears all instances and the room roster (session reset).



285
286
287
288
# File 'documented/common/creature/creature_base.rb', line 285

def clear
  instances.clear
  clear_room
end

#clear_room ⇒ void

This method returns an undefined value.

Empties the current-room roster (the persistent registry is untouched).

Called from the XML parser's nav and room-object refresh hooks; the roster is then rebuilt from fresh room XML.



251
252
253
254
255
# File 'documented/common/creature/creature_base.rb', line 251

def clear_room
  count = room_roster.size
  @current_room_ids = []
  respond "--- room: roster cleared (#{count} creature#{'s' unless count == 1})" if $creature_debug && count > 0
end

#configure(max_size: 1000, auto_register: true) ⇒ void

This method returns an undefined value.

Configures registry limits.

Every call resets omitted options to their defaults - max_size to 1000 and auto_register to true - so calling this with no arguments restores all defaults. Facade callers (e.g. Creature.configure(**options)) should pass every option they mean to keep.

Parameters:

  • max_size (Integer) (defaults to: 1000) —

    maximum number of retained instances.

  • auto_register (Boolean) (defaults to: true) —

    whether #register creates instances.



311
312
313
314
# File 'documented/common/creature/creature_base.rb', line 311

def configure(max_size: 1000, auto_register: true)
  @max_size = max_size
  @auto_register = auto_register
end

#current_room_ids ⇒ Array<Integer>

Returns the creature ids currently present in the room.

Hands back a copy, not the live roster. The internal roster is mutated in place by #mark_in_room / #clear_room, so a caller that mutated the returned array - the GemStone facade relied on this defensive copy before the extraction - would otherwise corrupt shared targeting state.

Returns:

  • (Array<Integer>)


265
266
267
# File 'documented/common/creature/creature_base.rb', line 265

def current_room_ids
  room_roster.dup
end

#debug_on(level = :changes) ⇒ Boolean, Symbol

Toggles live echo of status, flag, and registration changes.

Parameters:

  • level (Boolean, Symbol) (defaults to: :changes) —

    false disables debug output; true or :changes reports changes only; :all reports every <crtrStatus> flag; :active reports only active <crtrStatus> flags.

Returns:

  • (Boolean, Symbol) —

    the configured debug value.



374
375
376
# File 'documented/common/creature/creature_base.rb', line 374

def debug_on(level = :changes)
  $creature_debug = level
end

#full? ⇒ Boolean

Returns whether the registry is at capacity.

Returns:

  • (Boolean) —

    whether the registry is at capacity.



333
334
335
# File 'documented/common/creature/creature_base.rb', line 333

def full?
  size >= max_size
end

#in_room(*filters) ⇒ Array<Object>

Returns all tracked creatures currently in the room.

Unlike #targets this requires neither hostility nor target validity, so it also serves dead creatures, looting and wound inspection. Filters are ANDed and may name a status, a classification flag, or a not_ negation such as :not_prone; unknown filters match nothing.

Parameters:

  • filters (Array<String, Symbol>) —

    optional ANDed status/classification filters.

Returns:

  • (Array<Object>)


363
364
365
366
# File 'documented/common/creature/creature_base.rb', line 363

def in_room(*filters)
  candidates = room_roster.filter_map { |id| self[id] }
  apply_filters(candidates, filters)
end

#mark_in_room(id) ⇒ Boolean

Marks an id present in the current-room roster.

Parameters:

  • id (Integer, String) —

    server creature id.

Returns:

  • (Boolean) —

    true when the id was newly added.



237
238
239
240
241
242
243
# File 'documented/common/creature/creature_base.rb', line 237

def mark_in_room(id)
  id = id.to_i
  return false if room_roster.include?(id)

  room_roster << id
  true
end

#max_size ⇒ Integer

Returns configured maximum registry size (default 1000).

Returns:

  • (Integer) —

    configured maximum registry size (default 1000).



323
324
325
# File 'documented/common/creature/creature_base.rb', line 323

def max_size
  @max_size ||= 1000
end

#register(name, id, noun = nil) ⇒ Object?

Registers or looks up a creature instance, marking it present in the current room.

Room-marking happens on every call, new instance or not, because the feed event that triggers registration (a bolded room-object name, or a <crtrStatus> tag) is exactly the signal that the creature is present.

Parameters:

  • name (String, nil) —

    display name; may be nil when the feed supplies an id before a name (DragonRealms <crtrStatus>).

  • id (Integer, String) —

    server creature id.

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

    noun from room XML, when available.

Returns:

  • (Object, nil) —

    the registered instance, or nil when auto-registration is disabled or the registry is full.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'documented/common/creature/creature_base.rb', line 201

def register(name, id, noun = nil)
  # Record room presence first: the feed event that triggers this call
  # (a bolded room-object name or a <crtrStatus> tag) is itself proof the
  # creature is in the room, and that stays true even when
  # auto-registration is disabled and no instance will be created. Mark
  # before the guard so a known creature's room presence is still tracked
  # while auto-registration is off.
  entered_room = mark_in_room(id)
  return nil unless auto_register?

  existing = instances[id.to_i]
  if existing
    respond "--- #{name} (#{id}): in room" if entered_room && $creature_debug
    return existing
  end

  if full?
    # Progressively more aggressive: 120 minutes, then 15-minute steps.
    [7200, 6300, 5400, 4500, 3600, 2700, 1800, 900].each do |age_threshold|
      removed = cleanup_old(age_threshold)
      respond "--- Auto-cleanup: removed #{removed} old creatures (threshold: #{age_threshold}s)" if removed > 0 && $creature_debug
      break unless full?
    end
    return nil if full? # Still full after every cleanup attempt.
  end

  instance = new(id, noun, name)
  instances[id.to_i] = instance
  respond "--- #{name} (#{id}): registered" if $creature_debug
  instance
end

#size ⇒ Integer

Returns current number of retained instances.

Returns:

  • (Integer) —

    current number of retained instances.



328
329
330
# File 'documented/common/creature/creature_base.rb', line 328

def size
  instances.size
end

#targets(*filters) ⇒ Array<Object>

Returns attackable hostile creatures currently in the room.

Room membership comes from the creature roster (fed by XML room-object and <crtrStatus> events), not from any client last-selected-target control, which can go stale after movement or death. valid_target? (supplied by the game class) removes decoys/dead appendages and crtr_flag?(:hostile) supplies structured hostility.

Parameters:

  • filters (Array<String, Symbol>) —

    optional ANDed status/classification filters.

Returns:

  • (Array<Object>)


347
348
349
350
351
352
# File 'documented/common/creature/creature_base.rb', line 347

def targets(*filters)
  candidates = room_roster
               .filter_map { |id| self[id] }
               .select { |c| c.valid_target? && c.crtr_flag?(:hostile) }
  apply_filters(candidates, filters)
end