Module: Lich::DragonRealms::DRInfomon

Extended by:
Common::Watchable
Defined in:
documented/dragonrealms/drinfomon.rb,
documented/dragonrealms/drinfomon/startup.rb

Constant Summary collapse

DRINFOMON_CORE_LICH_DEFINES =

An array of core Lich defines used in DRInfomon.

Returns:

  • (Array<String>)

    the list of core defines

%W(drinfomon common common-arcana common-crafting common-healing common-healing-data common-items common-money common-moonmage common-summoning common-theurgy common-travel common-validation events slackbot equipmanager spellmonitor)
DRINFOMON_IN_CORE_LICH =

Indicates whether DRInfomon is included in the core Lich.

Returns:

  • (Boolean)

    true if included, false otherwise

true
DR_OBSOLETE_SCRIPTS =

Script names that are obsolete and should be deleted. Checked on login to warn users about stale files. List of obsolete script names that should be deleted.

Examples:

DR_OBSOLETE_SCRIPTS #=> ["events", "slackbot", ...]
%w[
  events slackbot spellmonitor exp-monitor
  common-travel common-validation common drinfomon equipmanager
  common-money common-moonmage common-summoning common-theurgy common-arcana
  bootstrap common-crafting common-healing-data common-healing common-items
  update-shops
].freeze
DR_OBSOLETE_DATA_FILES =

Data filenames that are obsolete and should be deleted. List of obsolete data filenames that should be deleted.

Examples:

DR_OBSOLETE_DATA_FILES #=> []
%w[].freeze
@@startup_complete =

Populates initial game state after login by issuing game commands whose output is parsed by DRParser.

Uses ExecScript so that fput blocks until the game responds, guaranteeing DRParser.parse has processed every response line before the next command is sent.

Called once from the game lifecycle hook in games.rb after the character name is known and the session is ready.

Detection from scripts:

DRInfomon.startup_complete? - true after all startup commands have finished.
Use this to avoid sending duplicate info/played/exp/ability commands.
false

Class Method Summary collapse

Methods included from Common::Watchable

watch!

Class Method Details

.post_startup_checksvoid

This method returns an undefined value.

Performs checks after the startup process to warn about obsolete scripts and data files.



103
104
105
106
107
108
109
110
111
# File 'documented/dragonrealms/drinfomon/startup.rb', line 103

def self.post_startup_checks
  warn_obsolete_scripts
  warn_obsolete_data_files
  warn_custom_scripts
  $setupfiles.reload if defined?($setupfiles) && $setupfiles
rescue StandardError => e
  safe_message('error', "DRInfomon: post_startup_checks failed: #{e.message}")
  safe_log("DRInfomon: post_startup_checks error: #{e.inspect}\n\t#{e.backtrace&.first(5)&.join("\n\t")}")
end

.safe_log(text) ⇒ void

This method returns an undefined value.

Logs a message safely, either through the logging system or to standard error.

Parameters:

  • text (String)

    the message text to log.



128
129
130
131
132
133
134
# File 'documented/dragonrealms/drinfomon/startup.rb', line 128

def self.safe_log(text)
  if defined?(Lich) && Lich.respond_to?(:log)
    Lich.log(text)
  else
    $stderr.puts(text)
  end
end

.safe_message(type, text) ⇒ void

This method returns an undefined value.

Sends a message safely, either through the messaging system or logs it directly.

Parameters:

  • type (String)

    the type of message (e.g., 'error', 'info')

  • text (String)

    the message text to send or log.



117
118
119
120
121
122
123
# File 'documented/dragonrealms/drinfomon/startup.rb', line 117

def self.safe_message(type, text)
  if defined?(Lich::Messaging) && Lich::Messaging.respond_to?(:msg)
    Lich::Messaging.msg(type, text)
  else
    safe_log(text)
  end
end

.startupvoid

This method returns an undefined value.

Executes the startup script to initialize game state.



53
54
55
# File 'documented/dragonrealms/drinfomon/startup.rb', line 53

def self.startup
  ExecScript.start(startup_script, { quiet: true, name: 'drinfomon_startup' })
end

.startup_complete?Boolean

Checks if the startup process is complete.

Returns:

  • (Boolean)

    true if startup commands have finished, false otherwise.



29
30
31
# File 'documented/dragonrealms/drinfomon/startup.rb', line 29

def self.startup_complete?
  @@startup_complete
end

.startup_completed!void

This method returns an undefined value.

Marks the startup process as complete and triggers post-startup checks.



95
96
97
98
99
# File 'documented/dragonrealms/drinfomon/startup.rb', line 95

def self.startup_completed!
  @@startup_complete = true
  PostLoad.game_loaded! if defined?(PostLoad)
  post_startup_checks
end

.startup_scriptString

Provides the script to be executed during startup.

Returns:

  • (String)

    the startup script containing game commands.



59
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
89
90
91
# File 'documented/dragonrealms/drinfomon/startup.rb', line 59

def self.startup_script
  <<~SCRIPT
    # Populate stats, race, guild, circle, etc.
    Lich::Util.issue_command("info", /^Name/, /^<output class=""/, quiet: true, timeout: 1) unless dead?

    # Populate account name and subscription level
    Lich::Util.issue_command("played", /^Account Info for/, quiet: true, timeout: 1)

    # Populate all skill ranks and learning rates
    Lich::Util.issue_command("exp all 0", /^Circle: \\d+/, /^EXP HELP/, quiet: true, timeout: 1)

    # Populate known spells/abilities/khri
    # The `ability` command works for all guilds:
    #   - Magic guilds: proxies to `spells`, parsed by check_known_spells
    #   - Barbarians: parsed by check_known_barbarian_abilities
    #   - Thieves: parsed by check_known_thief_khri
    Lich::Util.issue_command("ability", /^You (?:know the Berserks|recall the spells you have learned from your training)|^From (?:your apprenticeship you remember practicing|the \\w+ tree)/, /^You (?:recall that you have \\d+ training sessions|can use SPELL STANCE \\[HELP\\]|have \\d+ available slot)/, quiet: true, timeout: 1)

    # Ensure ShowRoomID and MonsterBold flags are enabled (one-time per character)
    unless UserVars.dependency_setflags
      flags = Array(Lich::Util.issue_command("flag", /^Usage/, /^For other setting options, see AVOID, SET, and TOGGLE/, quiet: true, timeout: 1, usexml: false))
      required = ["ShowRoomID", "MonsterBold"]
      required.each do |flag|
        fput("flag \#{flag} on") unless flags.any? { |f| f.match?(/\#{Regexp.escape(flag)}\\s+ON/) }
      end
      # Re-query to verify flags applied; only mark sentinel if all confirmed
      flags = Array(Lich::Util.issue_command("flag", /^Usage/, /^For other setting options, see AVOID, SET, and TOGGLE/, quiet: true, timeout: 1, usexml: false))
      UserVars.dependency_setflags = Time.now if required.all? { |flag| flags.any? { |f| f.match?(/\#{Regexp.escape(flag)}\\s+ON/) } }
    end

    Lich::DragonRealms::DRInfomon.startup_completed!
  SCRIPT
end

.warn_custom_scriptsvoid

This method returns an undefined value.

Warns the user if custom scripts shadow curated scripts.



182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'documented/dragonrealms/drinfomon/startup.rb', line 182

def self.warn_custom_scripts
  custom_dir = File.join(SCRIPT_DIR, 'custom')
  return unless File.directory?(custom_dir)

  custom_scripts = Dir.entries(custom_dir).select { |f| f.end_with?('.lic') }
  curated_scripts = Dir.entries(SCRIPT_DIR).select { |f| f.end_with?('.lic') }
  shadowed = custom_scripts.select { |script| curated_scripts.include?(script) }

  unless shadowed.empty?
    Lich::Messaging.msg("info", "NOTE: The following curated scripts are in your custom folder and will not receive updates")
    Lich::Messaging.msg("info", shadowed.join(', '))
  end
end

.warn_obsolete_data_filesvoid

This method returns an undefined value.

Warns the user about obsolete data files that can be safely deleted.



170
171
172
173
174
175
176
177
178
# File 'documented/dragonrealms/drinfomon/startup.rb', line 170

def self.warn_obsolete_data_files
  data_dir = File.join(SCRIPT_DIR, 'data')
  DR_OBSOLETE_DATA_FILES.each do |filename|
    path = File.join(data_dir, filename)
    next unless File.exist?(path)

    _respond Lich::Messaging.monsterbold("--- Lich: '#{filename}' is obsolete and can be safely deleted from #{data_dir}.")
  end
end

.warn_obsolete_scriptsvoid

This method returns an undefined value.

Warns the user about obsolete scripts that should be deleted.



159
160
161
162
163
164
165
166
# File 'documented/dragonrealms/drinfomon/startup.rb', line 159

def self.warn_obsolete_scripts
  DR_OBSOLETE_SCRIPTS.each do |script_name|
    path = File.join(SCRIPT_DIR, "#{script_name}.lic")
    next unless File.exist?(path)

    _respond Lich::Messaging.monsterbold("--- Lich: '#{script_name}.lic' is obsolete and should be deleted from #{SCRIPT_DIR}. It is no longer needed and may cause problems.")
  end
end

.watch!void

This method returns an undefined value.

Starts a thread to monitor the game state and execute startup commands.



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'documented/dragonrealms/drinfomon/startup.rb', line 35

def self.watch!
  @startup_thread ||= Thread.new do
    begin
      # Wait for character to be ready
      sleep 0.1 until GameBase::Game.autostarted? && XMLData.name && !XMLData.name.empty?

      # Run startup once
      startup
    rescue StandardError => e
      Lich::Messaging.msg('error', 'DRInfomon: Error in startup thread')
      Lich::Messaging.msg('error', "DRInfomon: #{e.inspect}")
      Lich::Messaging.msg('error', "DRInfomon: #{e.backtrace.join("\n")}")
    end
  end
end