Module: Lich::DragonRealms::DRInfomon
- Extended by:
- Common::Watchable
- Defined in:
- documented/dragonrealms/drinfomon/startup.rb,
documented/dragonrealms/drinfomon.rb
Overview
Populates initial game state after login and manages startup completion tracking.
Sends game commands (info, played, exp all 0, ability, flag) whose output is parsed by DRParser to populate XMLData with character stats, skills, spells, and other essential state. Uses ExecScript to ensure commands block until responses are parsed.
Scripts should check DRInfomon.startup_complete? before issuing their own info/played/exp/ability commands to avoid sending duplicates during initialization.
Includes automatic filesystem warnings about obsolete scripts and shadowed custom files.
Constant Summary collapse
- DRINFOMON_CORE_LICH_DEFINES =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
An array of core Lich defines used in DRInfomon.
%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 =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Indicates whether DRInfomon is included in the core Lich.
true- DR_OBSOLETE_SCRIPTS =
Script names that are obsolete and should be deleted. Checked on login to warn users about stale files.
%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.
%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
-
.post_startup_checks ⇒ void
Best-effort filesystem checks that run once after startup completes.
-
.safe_log(text) ⇒ void
Guarded logging -- safe to call if Lich.log is unavailable.
-
.safe_message(type, text) ⇒ void
Guarded messaging -- safe to call if Lich::Messaging is unavailable.
-
.startup ⇒ void
private
Runs the startup script that populates initial game state.
-
.startup_complete? ⇒ Boolean
Returns whether DRInfomon has finished populating initial game state after login.
-
.startup_completed! ⇒ void
private
Marks startup as complete and triggers post-startup housekeeping.
-
.startup_script ⇒ String
private
Generates the startup script content that populates game state.
-
.warn_custom_scripts ⇒ void
Warns when scripts/custom/ contains files that shadow curated scripts, preventing the curated versions from receiving updates.
-
.warn_obsolete_data_files ⇒ void
Warns about obsolete data files still present in SCRIPT_DIR/data.
-
.warn_obsolete_scripts ⇒ void
Warns about obsolete .lic files still present in SCRIPT_DIR.
-
.watch! ⇒ Object
Self-watching thread that triggers startup when ready Follows the ActiveSpell.watch! pattern for lifecycle management.
Methods included from Common::Watchable
Class Method Details
.post_startup_checks ⇒ void
This method returns an undefined value.
Best-effort filesystem checks that run once after startup completes. These don't need game commands, just file existence checks and warnings. Failures are logged but do not block the PostLoad lifecycle.
146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 146 def self.post_startup_checks warn_obsolete_scripts warn_obsolete_data_files warn_custom_scripts $setupfiles.reload if defined?($setupfiles) && $setupfiles # Drop CustomSubstitutions' memoized lists so a fresh login re-reads any # edited custom_* settings (its cache is separate from $setupfiles'). Lich::DragonRealms::CustomSubstitutions.reset! if defined?(Lich::DragonRealms::CustomSubstitutions) rescue StandardError => e ('error', "DRInfomon: post_startup_checks failed: #{e.}") 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.
Guarded logging -- safe to call if Lich.log is unavailable.
176 177 178 179 180 181 182 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 176 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.
Guarded messaging -- safe to call if Lich::Messaging is unavailable.
164 165 166 167 168 169 170 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 164 def self.(type, text) if defined?(Lich::Messaging) && Lich::Messaging.respond_to?(:msg) Lich::Messaging.msg(type, text) else safe_log(text) end end |
.startup ⇒ void
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.
Runs the startup script that populates initial game state.
Executes startup_script via ExecScript with quiet mode and a descriptive name. Called once by the watch! lifecycle hook after the character is ready.
74 75 76 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 74 def self.startup ExecScript.start(startup_script, { quiet: true, name: 'drinfomon_startup' }) end |
.startup_complete? ⇒ Boolean
Returns whether DRInfomon has finished populating initial game state after login.
45 46 47 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 45 def self.startup_complete? @@startup_complete end |
.startup_completed! ⇒ void
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.
Marks startup as complete and triggers post-startup housekeeping.
Sets the startup_complete flag to true, calls PostLoad.game_loaded! if available, and runs post_startup_checks to warn about obsolete and shadowed scripts.
135 136 137 138 139 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 135 def self.startup_completed! @@startup_complete = true PostLoad.game_loaded! if defined?(PostLoad) post_startup_checks end |
.startup_script ⇒ String
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.
Generates the startup script content that populates game state.
Constructs a heredoc string containing game commands issued in order:
- info: populates character stats (name, race, guild, circle)
- played: populates account name and subscription level
- exp all 0: populates all skill ranks and learning rates
- ability: populates spells, barbarian abilities, or thief khri (guild-dependent)
- flag: ensures MonsterBold is enabled (one-time per character)
Each command uses Lich::Util.issue_command with regex patterns and 1-second timeout. Completes by calling startup_completed! to signal readiness.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 92 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 the MonsterBold flag is enabled (one-time per character). ShowRoomID is no # longer forced: room UIDs now come from the <nav> tag regardless of that flag, so # whether the game shows inline room IDs is left entirely to the player's preference. 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 = ["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_scripts ⇒ void
This method returns an undefined value.
Warns when scripts/custom/ contains files that shadow curated scripts, preventing the curated versions from receiving updates.
226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 226 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_files ⇒ void
This method returns an undefined value.
Warns about obsolete data files still present in SCRIPT_DIR/data.
212 213 214 215 216 217 218 219 220 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 212 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_scripts ⇒ void
This method returns an undefined value.
Warns about obsolete .lic files still present in SCRIPT_DIR.
200 201 202 203 204 205 206 207 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 200 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! ⇒ Object
Self-watching thread that triggers startup when ready Follows the ActiveSpell.watch! pattern for lifecycle management
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'documented/dragonrealms/drinfomon/startup.rb', line 51 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 |