Module: Lich
- Included in:
- DragonRealms, Gemstone
- Defined in:
- documented/lich.rb,
documented/games.rb,
documented/stash.rb,
documented/update.rb,
documented/gemcheck.rb,
documented/messaging.rb,
documented/util/opts.rb,
documented/util/util.rb,
documented/common/gtk.rb,
documented/common/hmr.rb,
documented/common/log.rb,
documented/magic-info.rb,
documented/common/vars.rb,
documented/gemstone/sk.rb,
documented/global_defs.rb,
documented/common/spell.rb,
documented/common/buffer.rb,
documented/common/script.rb,
documented/gemstone/disk.rb,
documented/gemstone/gift.rb,
documented/gemstone/psms.rb,
documented/common/account.rb,
documented/common/gameobj.rb,
documented/common/pipe_io.rb,
documented/gemstone/claim.rb,
documented/gemstone/group.rb,
documented/gemstone/scars.rb,
documented/main/help_text.rb,
documented/attributes/char.rb,
documented/common/db_store.rb,
documented/common/frontend.rb,
documented/common/frontend.rb,
documented/common/postload.rb,
documented/common/settings.rb,
documented/common/throttle.rb,
documented/common/uservars.rb,
documented/common/watchfor.rb,
documented/gemstone/bounty.rb,
documented/gemstone/wounds.rb,
documented/main/early_exit.rb,
documented/attributes/stats.rb,
documented/bundler_recovery.rb,
documented/common/gui/state.rb,
documented/common/gui_login.rb,
documented/common/inventory.rb,
documented/common/watchable.rb,
documented/common/xmlparser.rb,
documented/gemstone/effects.rb,
documented/gemstone/infomon.rb,
documented/gemstone/injured.rb,
documented/gemstone/society.rb,
documented/util/deep_freeze.rb,
documented/attributes/skills.rb,
documented/attributes/spells.rb,
documented/common/arg_parser.rb,
documented/common/gameloader.rb,
documented/common/map/map_dr.rb,
documented/common/map/map_gs.rb,
documented/gemstone/creature.rb,
documented/gemstone/currency.rb,
documented/gemstone/stowlist.rb,
documented/main/argv_options.rb,
documented/util/textstripper.rb,
documented/common/setup_files.rb,
documented/gemstone/armaments.rb,
documented/gemstone/critranks.rb,
documented/gemstone/overwatch.rb,
documented/gemstone/psms/cman.rb,
documented/gemstone/psms/feat.rb,
documented/gemstone/readylist.rb,
documented/main/startup_theme.rb,
documented/api/active_sessions.rb,
documented/common/limitedarray.rb,
documented/common/map/map_base.rb,
documented/common/script_death.rb,
documented/common/sharedbuffer.rb,
documented/common/shutdown_log.rb,
documented/common/upstreamhook.rb,
documented/common/xml_entities.rb,
documented/dependency_recovery.rb,
documented/gemstone/experience.rb,
documented/gemstone/psms/armor.rb,
documented/gemstone/spellranks.rb,
documented/util/gtk_compaction.rb,
documented/util/memoryreleaser.rb,
documented/attributes/enhancive.rb,
documented/attributes/resources.rb,
documented/attributes/spellsong.rb,
documented/common/feature_flags.rb,
documented/common/gui/utilities.rb,
documented/common/hook_registry.rb,
documented/gemstone/bounty/task.rb,
documented/gemstone/infomon/cli.rb,
documented/gemstone/psms/shield.rb,
documented/gemstone/psms/warcry.rb,
documented/gemstone/psms/weapon.rb,
documented/common/downstreamhook.rb,
documented/common/gui/components.rb,
documented/dragonrealms/creature.rb,
documented/gemstone/psms/qstrike.rb,
documented/common/gui/theme_utils.rb,
documented/common/ruby_executable.rb,
documented/common/shutdown_intent.rb,
documented/dragonrealms/drinfomon.rb,
documented/gemstone/bounty/parser.rb,
documented/gemstone/combat/parser.rb,
documented/gemstone/infomon/cache.rb,
documented/main/arg_normalization.rb,
documented/main/reconnect_command.rb,
documented/common/credential_scrub.rb,
documented/common/frontend_locator.rb,
documented/common/orderly_shutdown.rb,
documented/common/process_launcher.rb,
documented/common/session_launcher.rb,
documented/common/socket_read_hook.rb,
documented/gemstone/combat/tracker.rb,
documented/gemstone/infomon/parser.rb,
documented/gemstone/infomon/status.rb,
documented/gemstone/psms/ascension.rb,
documented/main/user_exit_dispatch.rb,
documented/common/frontend_launcher.rb,
documented/common/frontend_settings.rb,
documented/common/gui/accessibility.rb,
documented/common/gui/conversion_ui.rb,
documented/common/session_lifecycle.rb,
documented/common/shutdown_watchdog.rb,
documented/gemstone/combat/defs/ucs.rb,
documented/gemstone/combat/recorder.rb,
documented/main/bind_address_option.rb,
documented/common/authentication/cli.rb,
documented/common/authentication/gui.rb,
documented/common/bind_host_resolver.rb,
documented/common/cli/cli_conversion.rb,
documented/common/gui/game_selection.rb,
documented/common/saga_launch_policy.rb,
documented/common/saga_managed_login.rb,
documented/common/socketconfigurator.rb,
documented/common/update/file_writer.rb,
documented/common/update/script_sync.rb,
documented/gemstone/combat/observers.rb,
documented/gemstone/combat/processor.rb,
documented/common/gui/account_manager.rb,
documented/common/gui/login_tab_utils.rb,
documented/common/gui/password_change.rb,
documented/common/gui/password_cipher.rb,
documented/common/gui/saved_login_tab.rb,
documented/common/gui/window_settings.rb,
documented/common/reusable_tcp_server.rb,
documented/common/update/custom_repos.rb,
documented/common/update/file_updater.rb,
documented/gemstone/infomon/xmlparser.rb,
documented/common/gui/manual_login_tab.rb,
documented/common/gui/password_manager.rb,
documented/common/gui/tab_communicator.rb,
documented/common/settings_transformer.rb,
documented/common/shutdown_coordinator.rb,
documented/common/update/github_client.rb,
documented/common/windows_command_line.rb,
documented/dragonrealms/commons/common.rb,
documented/gemstone/combat/defs/damage.rb,
documented/gemstone/combat/defs/flares.rb,
documented/gemstone/combat/defs/spells.rb,
documented/common/class_exts/stringproc.rb,
documented/common/cli/cli_orchestration.rb,
documented/common/gui/favorites_manager.rb,
documented/common/gui/frontend_selector.rb,
documented/common/gui/parameter_objects.rb,
documented/common/saga_managed_launcher.rb,
documented/common/settings/charsettings.rb,
documented/common/settings/gamesettings.rb,
documented/common/shutdown_script_drain.rb,
documented/gemstone/combat/defs/attacks.rb,
documented/gemstone/infomon/activespell.rb,
documented/internal_api/active_sessions.rb,
documented/common/authentication/eaccess.rb,
documented/common/creature/creature_base.rb,
documented/common/gui/account_manager_ui.rb,
documented/common/update/status_reporter.rb,
documented/common/update/tracked_scripts.rb,
documented/dragonrealms/commons/slackbot.rb,
documented/dragonrealms/drinfomon/drdefs.rb,
documented/dragonrealms/drinfomon/drroom.rb,
documented/dragonrealms/drinfomon/events.rb,
documented/gemstone/combat/defs/assaults.rb,
documented/gemstone/combat/defs/outcomes.rb,
documented/gemstone/combat/defs/statuses.rb,
documented/main/detachable_client_notice.rb,
documented/main/detachable_client_target.rb,
documented/common/client_input_dispatcher.rb,
documented/common/settings/path_navigator.rb,
documented/common/settings/settings_proxy.rb,
documented/common/update/branch_installer.rb,
documented/common/update/channel_resolver.rb,
documented/common/update/snapshot_manager.rb,
documented/dragonrealms/drinfomon/drskill.rb,
documented/dragonrealms/drinfomon/drstats.rb,
documented/dragonrealms/drinfomon/startup.rb,
documented/gemstone/armaments/armor_stats.rb,
documented/gemstone/combat/defs/sequences.rb,
documented/common/authentication/web_login.rb,
documented/common/cli/cli_option_validator.rb,
documented/common/cli/cli_options_registry.rb,
documented/common/gui/frontend_manager_tab.rb,
documented/common/update/release_installer.rb,
documented/dragonrealms/drinfomon/drparser.rb,
documented/dragonrealms/drinfomon/drspells.rb,
documented/gemstone/armaments/shield_stats.rb,
documented/gemstone/armaments/weapon_stats.rb,
documented/gemstone/combat/async_processor.rb,
documented/common/cli/active_sessions_query.rb,
documented/common/settings/database_adapter.rb,
documented/dragonrealms/drinfomon/drbanking.rb,
documented/gemstone/societies/order_of_voln.rb,
documented/common/authentication/entry_store.rb,
documented/common/authentication/launch_data.rb,
documented/common/detachable_client_registry.rb,
documented/common/gui/encryption_mode_change.rb,
documented/common/gui/master_password_change.rb,
documented/common/gui/master_password_prompt.rb,
documented/common/settings/instance_settings.rb,
documented/common/settings/sessions_settings.rb,
documented/common/shutdown_result_predicates.rb,
documented/dragonrealms/commons/common-items.rb,
documented/dragonrealms/commons/common-money.rb,
documented/dragonrealms/commons/equipmanager.rb,
documented/dragonrealms/custom_substitutions.rb,
documented/gemstone/combat/defs/pattern_gate.rb,
documented/gemstone/combat/defs/spell_losses.rb,
documented/common/authentication/cli_password.rb,
documented/common/gui/master_password_manager.rb,
documented/dragonrealms/commons/common-arcana.rb,
documented/dragonrealms/commons/common-travel.rb,
documented/dragonrealms/drinfomon/drvariables.rb,
documented/common/authentication/authenticator.rb,
documented/common/authentication/launch_result.rb,
documented/common/authentication/login_helpers.rb,
documented/common/best_effort_shutdown_cleanup.rb,
documented/common/gui/manual_frontend_selector.rb,
documented/dragonrealms/commons/common-healing.rb,
documented/dragonrealms/commons/common-theurgy.rb,
documented/dragonrealms/drinfomon/drexpmonitor.rb,
documented/gemstone/societies/council_of_light.rb,
documented/internal_api/active_sessions/client.rb,
documented/internal_api/active_sessions/server.rb,
documented/common/class_exts/synchronizedsocket.rb,
documented/common/gui/master_password_prompt_ui.rb,
documented/dragonrealms/commons/common-crafting.rb,
documented/dragonrealms/commons/common-moonmage.rb,
documented/common/cli/cli_encryption_mode_change.rb,
documented/common/gui/windows_credential_manager.rb,
documented/dragonrealms/commons/common-summoning.rb,
documented/gemstone/armaments/weapon_stats_blunt.rb,
documented/gemstone/armaments/weapon_stats_edged.rb,
documented/internal_api/active_sessions/registry.rb,
documented/dragonrealms/commons/common-money-data.rb,
documented/dragonrealms/commons/common-validation.rb,
documented/gemstone/armaments/weapon_stats_hybrid.rb,
documented/gemstone/armaments/weapon_stats_ranged.rb,
documented/gemstone/armaments/weapon_stats_thrown.rb,
documented/internal_api/active_sessions/lifecycle.rb,
documented/dragonrealms/dependency/settings_config.rb,
documented/gemstone/armaments/weapon_stats_natural.rb,
documented/gemstone/armaments/weapon_stats_polearm.rb,
documented/gemstone/armaments/weapon_stats_unarmed.rb,
documented/gemstone/societies/guardians_of_sunfist.rb,
documented/common/settings/session_database_adapter.rb,
documented/dragonrealms/commons/common-healing-data.rb,
documented/gemstone/armaments/weapon_stats_brawling.rb,
documented/gemstone/armaments/weapon_stats_runestave.rb,
documented/gemstone/armaments/weapon_stats_two_handed.rb
Overview
Namespace for the Lich 5 scripting engine and its public API.
Defined Under Namespace
Modules: API, Claim, Common, DragonRealms, GameBase, GemCheck, Gemstone, InternalAPI, Main, Messaging, Resources, Stash, Unknown, Util Classes: BundlerRecovery, DependencyRecovery
Constant Summary collapse
- DEFAULT_SQLITE_BUSY_TIMEOUT_MS =
Default timeout in milliseconds for SQLite3 busy waits when the database is locked.
5000- ROOMID_LOCATIONS =
The valid values for Lich.display_roomid_location.
%w[title line both].freeze
- MAX_DEBUG_LOGS_DEFAULT =
Default number of debug log files to retain when no user preference is set.
20- MAX_DEBUG_LOGS_MINIMUM =
Minimum allowed value for max_debug_logs to prevent accidental deletion of all log files.
1- @@hosts_file =
nil- @@lich_db =
nil- @@last_warn_deprecated =
0- @@deprecated_log =
[]
- @@display_lichid =
settings
nil- @@display_uid =
boolean
nil- @@display_exits =
boolean
nil- @@display_stringprocs =
boolean
nil- @@display_room_links =
boolean
nil- @@display_room_mono =
boolean
nil- @@display_expgains =
boolean
nil- @@display_roomid_location =
boolean (DragonRealms only)
nil- @@hide_uid_flag =
string (DragonRealms only): "title" | "line" | "both"
nil- @@track_autosort_state =
boolean
nil- @@track_dark_mode =
boolean
nil- @@track_layout_state =
boolean
nil- @@track_persistent_launcher_mode =
boolean
nil- @@debug_messaging =
boolean
nil- @@max_debug_logs =
boolean
nil
Class Method Summary collapse
-
.break_game_host_port(gamehost, gameport) ⇒ Array<(String, Integer)>
Converts current game server hostnames and ports back to their deprecated equivalents (inverse of Lich.fix_game_host_port).
-
.class_eval(*_a) ⇒ nil
private
Stub implementation that prevents dynamic class evaluation.
-
.class_variable_get(*_a) ⇒ nil
private
Stub implementation that prevents access to class variables.
-
.cleanup_debug_logs(temp_dir) ⇒ void
Removes old debug log files from
temp_dir, keeping at most Lich.max_debug_logs files. -
.configure_sqlite_connection(db) ⇒ SQLite3::Database
Configures an SQLite3 database connection with the busy timeout setting.
-
.core_updated_with_lich_version ⇒ String
private
Retrieves the Lich version string recorded at the last core update.
-
.core_updated_with_lich_version=(val) ⇒ void
private
Records the Lich version at core update time.
-
.db ⇒ SQLite3::Database
Returns the primary SQLite3 database connection, creating it on first access.
-
.db_maint_due?(months = 6) ⇒ Boolean
Checks whether database maintenance is due based on elapsed time since last run.
-
.db_maint_last_at ⇒ String?
Retrieves the timestamp of the last database maintenance operation from lich_settings.
-
.db_maint_lock_path ⇒ Object
--- Minimal DB maintenance helpers (simple + safe) --- Stores last maintenance timestamp and summary in lich_settings.
-
.db_maint_set!(iso_utc, note = '') ⇒ void
Records a database maintenance completion timestamp and optional note in lich_settings.
-
.db_mutex ⇒ Mutex
private
Returns the module-level mutex used to serialize database access.
-
.db_vacuum_if_due!(months: 6, lock_timeout_s: 0.5) ⇒ Object
Try VACUUM if due.
-
.debug_messaging ⇒ Boolean
Returns the debug messaging toggle state, lazily loaded from lich_settings.
-
.debug_messaging=(val) ⇒ void
Sets and persists the debug messaging toggle state.
-
.deprecated(old_object = '', new_object = '', script_location = "#{Script.current.name || 'unknown'}", debug_log: true, fe_log: false, limit_log: true) ⇒ void
Records a deprecation notice for an old API call and optionally logs it.
-
.display_exits ⇒ Boolean?
Returns the room exits display toggle.
-
.display_exits=(val) ⇒ void
Sets and persists the room exits display toggle.
-
.display_expgains ⇒ Boolean?
Returns the experience gains display toggle.
-
.display_expgains=(val) ⇒ void
Sets and persists the experience gains display toggle.
-
.display_lichid ⇒ Boolean?
Returns the room ID display toggle, defaulting based on game type.
-
.display_lichid=(val) ⇒ void
Sets and persists the room ID display toggle.
-
.display_room_links ⇒ Boolean?
Whether room exits are rendered as clickable command links (a
tag) or as plain text in room-display output. -
.display_room_links=(val) ⇒ Boolean, String
Sets and persists the room-exit link toggle.
-
.display_room_mono ⇒ Boolean?
Whether the Lich-injected room lines (Room Number, Room Exits, StringProcs) are wrapped in the fixed-width mono style.
-
.display_room_mono=(val) ⇒ Boolean, String
Sets and persists the room-line mono-font toggle.
-
.display_roomid_location ⇒ String?
Where DragonRealms renders the optional room id / UID chosen via ;display lichid and ;display uid: "title" injects into the room-name line (visible on every front-end), "line" is the historical "Room Number:" line below the room, and "both" does both.
-
.display_roomid_location=(val) ⇒ void
Sets the DragonRealms room-id display placement and persists it.
-
.display_stringprocs ⇒ Boolean?
Returns the StringProcs display toggle.
-
.display_stringprocs=(val) ⇒ void
Sets and persists the StringProcs display toggle.
-
.display_uid ⇒ Boolean?
Returns the UID (unique ID) display toggle, defaulting based on game type.
-
.display_uid=(val) ⇒ void
Sets and persists the UID display toggle.
-
.find_hosts_file ⇒ String, false
Searches the system for the hosts file and caches its path.
-
.fix_game_host_port(gamehost, gameport) ⇒ Array<(String, Integer)>
Normalizes deprecated game server hostnames and ports to current values.
-
.get_simu_launcher ⇒ String?
private
Retrieves the path or command of the Simutronics Game Entry (SGE) launcher from the system registry.
-
.hide_uid_flag ⇒ Boolean?
Returns the UID hiding toggle state.
-
.hide_uid_flag=(val) ⇒ void
Sets and persists the UID hiding toggle state.
-
.hosts_file ⇒ String, false
Returns the path to the system hosts file, locating it on first access.
-
.init_db ⇒ void
private
Initializes the Lich database schema, creating all required tables and indices.
-
.inventory_boxes(player_id) ⇒ Boolean
Checks whether inventory boxes are enabled for a given player.
-
.link_to_sal ⇒ Boolean?
private
Integrates Lich into Simutronics AutoLaunch (browser launcher) by modifying the registry.
-
.link_to_sge ⇒ Boolean?
private
Integrates Lich into the Simutronics Game Entry launcher by modifying the registry.
-
.log(msg) ⇒ void
Writes a timestamped message to stderr (the debug log).
-
.max_debug_logs ⇒ Integer
Returns the maximum number of debug log files to retain in the temp directory.
-
.max_debug_logs=(val) ⇒ void
Persists the maximum number of debug log files to retain.
-
.method_missing(arg1, arg2 = '') ⇒ Object
deprecated
Deprecated.
Use Vars class instead
-
.modify_hosts(game_host) ⇒ Boolean
private
Adds a hosts file entry redirecting a game hostname to 127.0.0.1 for local testing.
-
.module_eval(*_a) ⇒ nil
private
Stub implementation that prevents dynamic module evaluation.
-
.msgbox(args) ⇒ Symbol?
private
Displays a modal message box dialog using the native platform GUI or terminal fallback.
-
.mutex_lock ⇒ void
private
Acquires the database mutex lock if not already held by the current thread.
-
.mutex_unlock ⇒ void
private
Releases the database mutex lock if currently held by the current thread.
-
.open_sequel_sqlite(path) ⇒ Sequel::Database
Opens an SQLite database via the Sequel ORM and sets the busy timeout via PRAGMA.
-
.open_sqlite_db(path) ⇒ SQLite3::Database
Opens or creates an SQLite3 database at the specified path and applies busy timeout configuration.
-
.restore_hosts ⇒ void
private
Restores the hosts file from its backup if present.
-
.seek(fe) ⇒ String?
Locates the installation directory of a frontend by name.
-
.set_inventory_boxes(player_id, enabled) ⇒ void
Enables or disables inventory boxes for a given player.
-
.show_deprecated_log ⇒ void
Displays all recorded deprecation notices to the user via respond().
-
.sqlite_busy_timeout_ms ⇒ Integer
Returns the configured SQLite busy timeout in milliseconds.
-
.track_autosort_state ⇒ Boolean
Returns the autosort state tracking toggle.
-
.track_autosort_state=(val) ⇒ void
Sets and persists the autosort state tracking toggle.
-
.track_dark_mode ⇒ Boolean
Returns the dark mode state tracking toggle.
-
.track_dark_mode=(val) ⇒ void
Sets and persists the dark mode state tracking toggle.
-
.track_layout_state ⇒ Boolean
Returns the layout state tracking toggle.
-
.track_layout_state=(val) ⇒ void
Sets and persists the layout state tracking toggle.
-
.track_persistent_launcher_mode ⇒ Boolean
Returns persisted launcher mode state for GUI login flow.
-
.track_persistent_launcher_mode=(val) ⇒ void
Persists launcher mode state for GUI login flow.
-
.unlink_from_sal ⇒ Boolean?
private
Removes Lich integration from Simutronics AutoLaunch by restoring the original registry.
-
.unlink_from_sge ⇒ Boolean?
private
Removes Lich integration from the Simutronics Game Entry launcher by restoring the original registry.
-
.win32_launch_method ⇒ String?
private
Retrieves the stored Windows launch method preference from lich_settings.
-
.win32_launch_method=(val) ⇒ void
private
Stores a Windows launch method preference in lich_settings.
Class Method Details
.break_game_host_port(gamehost, gameport) ⇒ Array<(String, Integer)>
Maps: storm.gs4.game.play.net:10124 and storm.gs4.game.play.net:10024 and dr.simutronics.net:11024 to their original aliases
Converts current game server hostnames and ports back to their deprecated equivalents (inverse of fix_game_host_port).
956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 |
# File 'documented/lich.rb', line 956 def self.break_game_host_port(gamehost, gameport) if (gamehost == 'storm.gs4.game.play.net') and (gameport.to_i == 10324) gamehost = 'gs4.simutronics.net' gameport = 10321 elsif (gamehost == 'storm.gs4.game.play.net') and (gameport.to_i == 10124) gamehost = 'gs-plat.simutronics.net' gameport = 10121 elsif (gamehost == 'storm.gs4.game.play.net') and (gameport.to_i == 10024) gamehost = 'gs3.simutronics.net' gameport = 4900 elsif (gamehost == 'dr.simutronics.net') and (gameport.to_i == 11024) gamehost = 'prime.dr.game.play.net' gameport = 4901 end [gamehost, gameport] end |
.class_eval(*_a) ⇒ nil
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.
Stub implementation that prevents dynamic class evaluation.
328 |
# File 'documented/lich.rb', line 328 def self.class_eval(*_a); nil; end |
.class_variable_get(*_a) ⇒ nil
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.
Stub implementation that prevents access to class variables.
322 |
# File 'documented/lich.rb', line 322 def self.class_variable_get(*_a); nil; end |
.cleanup_debug_logs(temp_dir) ⇒ void
This method returns an undefined value.
Removes old debug log files from temp_dir, keeping at most
max_debug_logs files. Files are sorted lexicographically by name
(which encodes a timestamp), so the most recent files are retained.
This method is called once during Lich startup (in init.rb) after the
database has been initialized.
1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 |
# File 'documented/lich.rb', line 1560 def self.cleanup_debug_logs(temp_dir) pattern = /^debug(?:-\d+)+\.log$/ candidates = Dir.entries(temp_dir).select { |fn| fn.match?(pattern) } limit = Lich.max_debug_logs return if candidates.length <= limit candidates.sort.reverse[limit..-1].each do |old_file| begin File.delete(File.join(temp_dir, old_file)) rescue Lich.log "error: #{$!}\n\t#{$!.backtrace.join("\n\t")}" end end end |
.configure_sqlite_connection(db) ⇒ SQLite3::Database
If the database object does not respond to busy_timeout, it is returned unchanged
Configures an SQLite3 database connection with the busy timeout setting.
22 23 24 25 |
# File 'documented/lich.rb', line 22 def self.configure_sqlite_connection(db) db.busy_timeout(sqlite_busy_timeout_ms) if db.respond_to?(:busy_timeout) db end |
.core_updated_with_lich_version ⇒ 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.
Retries on SQLite3::BusyException
Retrieves the Lich version string recorded at the last core update.
1081 1082 1083 1084 1085 1086 1087 1088 1089 |
# File 'documented/lich.rb', line 1081 def self.core_updated_with_lich_version begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='core_updated_with_lich_version';") rescue SQLite3::BusyException sleep 0.1 retry end return val.to_s end |
.core_updated_with_lich_version=(val) ⇒ 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.
Retries on SQLite3::BusyException
This method returns an undefined value.
Records the Lich version at core update time.
1097 1098 1099 1100 1101 1102 1103 1104 |
# File 'documented/lich.rb', line 1097 def self.core_updated_with_lich_version=(val) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('core_updated_with_lich_version',?);", [val.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.db ⇒ SQLite3::Database
Connection is cached in @@lich_db; the database file is created if it does not exist
Returns the primary SQLite3 database connection, creating it on first access.
267 268 269 |
# File 'documented/lich.rb', line 267 def self.db @@lich_db ||= open_sqlite_db("#{DATA_DIR}/lich.db3") end |
.db_maint_due?(months = 6) ⇒ Boolean
Returns true on parsing errors to allow maintenance to attempt
Checks whether database maintenance is due based on elapsed time since last run.
97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'documented/lich.rb', line 97 def self.db_maint_due?(months = 6) last = Lich.db_maint_last_at return true if last.nil? || last.empty? begin cutoff = Time.now.utc - (months * 30 * 24 * 60 * 60) last_t = Time.parse(last) rescue nil return true if last_t.nil? last_t < cutoff rescue => e Lich.log "db_maint_due? parse error: #{e}" true end end |
.db_maint_last_at ⇒ String?
Retries on SQLite3::BusyException; returns nil on other errors
Retrieves the timestamp of the last database maintenance operation from lich_settings.
60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'documented/lich.rb', line 60 def self.db_maint_last_at ts = nil begin ts = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='db_maint_last_at';") rescue SQLite3::BusyException sleep 0.1 retry rescue => e Lich.log "db_maint_last_at error: #{e}" end ts end |
.db_maint_lock_path ⇒ Object
--- Minimal DB maintenance helpers (simple + safe) --- Stores last maintenance timestamp and summary in lich_settings. Uses an advisory OS file lock so only one Lich instance attempts VACUUM.
52 53 54 |
# File 'documented/lich.rb', line 52 def self.db_maint_lock_path File.join(DATA_DIR, 'lich.db3.maint.lock') end |
.db_maint_set!(iso_utc, note = '') ⇒ void
Retries on SQLite3::BusyException; creates lich_settings table if needed
This method returns an undefined value.
Records a database maintenance completion timestamp and optional note in lich_settings.
79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'documented/lich.rb', line 79 def self.db_maint_set!(iso_utc, note = '') begin Lich.db.execute("CREATE TABLE IF NOT EXISTS lich_settings (name TEXT NOT NULL, value TEXT, PRIMARY KEY(name));") Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name, value) VALUES('db_maint_last_at', ?);", [iso_utc]) Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name, value) VALUES('db_maint_last_note', ?);", [note.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry rescue => e Lich.log "db_maint_set! error: #{e}" end end |
.db_mutex ⇒ Mutex
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 module-level mutex used to serialize database access.
200 201 202 |
# File 'documented/lich.rb', line 200 def self.db_mutex @@db_mutex end |
.db_vacuum_if_due!(months: 6, lock_timeout_s: 0.5) ⇒ Object
Try VACUUM if due. If the DB is busy (another process), skip and try next run.
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'documented/lich.rb', line 112 def self.db_vacuum_if_due!(months: 6, lock_timeout_s: 0.5) return :skipped_recent unless Lich.db_maint_due?(months) lock_path = Lich.db_maint_lock_path File.open(lock_path, File::RDWR | File::CREAT, 0o644) do |f| start = Time.now got = false begin got = f.flock(File::LOCK_EX | File::LOCK_NB) rescue => e Lich.log "db_maint flock error: #{e}" end unless got while (Time.now - start) < lock_timeout_s && !got sleep 0.1 begin got = f.flock(File::LOCK_EX | File::LOCK_NB) rescue SystemCallError, IOError # Transient error acquiring lock on some filesystems; back off and retry. sleep 0.05 end end end return :skipped_lock_held unless got begin page_count_before = Lich.db.get_first_value('PRAGMA page_count;').to_i freelist_count_before = Lich.db.get_first_value('PRAGMA freelist_count;').to_i rescue SQLite3::BusyException Lich.log "db_maint: busy reading stats; skipping" return :skipped_busy end begin mode = Lich.db.get_first_value('PRAGMA journal_mode;') if mode && mode.to_s.strip.upcase == 'WAL' Lich.db.execute('PRAGMA wal_checkpoint(TRUNCATE);') end rescue SQLite3::SQLException => e Lich.log "db_maint: checkpoint skipped (#{e.class}: #{e.})" end begin Lich.db.execute('VACUUM;') rescue SQLite3::BusyException => e Lich.log "db_maint: VACUUM busy; skipping (#{e.})" return :skipped_busy rescue => e Lich.log "db_maint: VACUUM error: #{e}" return :error end page_count_after = Lich.db.get_first_value('PRAGMA page_count;').to_i rescue 0 freelist_count_after = Lich.db.get_first_value('PRAGMA freelist_count;').to_i rescue 0 note = "VACUUM ok pages #{page_count_before}->#{page_count_after}, free #{freelist_count_before}->#{freelist_count_after}" Lich.db_maint_set!(Time.now.utc.iso8601, note) :vacuum_ok end end |
.debug_messaging ⇒ Boolean
Lazily evaluates from database on first call and caches in @@debug_messaging
Returns the debug messaging toggle state, lazily loaded from lich_settings.
979 980 981 982 983 984 985 986 987 988 989 990 991 |
# File 'documented/lich.rb', line 979 def self.debug_messaging if @@debug_messaging.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='debug_messaging';") rescue SQLite3::BusyException sleep 0.1 retry end @@debug_messaging = (val.to_s =~ /on|true|yes/ ? true : false) Lich.debug_messaging = @@debug_messaging end return @@debug_messaging end |
.debug_messaging=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the debug messaging toggle state.
998 999 1000 1001 1002 1003 1004 1005 1006 |
# File 'documented/lich.rb', line 998 def self.debug_messaging=(val) @@debug_messaging = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('debug_messaging',?);", [@@debug_messaging.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.deprecated(old_object = '', new_object = '', script_location = "#{Script.current.name || 'unknown'}", debug_log: true, fe_log: false, limit_log: true) ⇒ void
Deduplication tracks messages in @@deprecated_log; use show_deprecated_log to display accumulated notices
This method returns an undefined value.
Records a deprecation notice for an old API call and optionally logs it.
355 356 357 358 359 360 361 |
# File 'documented/lich.rb', line 355 def self.deprecated(old_object = '', new_object = '', script_location = "#{Script.current.name || 'unknown'}", debug_log: true, fe_log: false, limit_log: true) msg = "Deprecated call to #{old_object} used in #{script_location}. Please change to #{new_object} instead!" return if limit_log && @@deprecated_log.include?(msg) Lich.log(msg) if debug_log Lich::Messaging.msg("bold", msg) if fe_log @@deprecated_log.push(msg) unless @@deprecated_log.include?(msg) end |
.display_exits ⇒ Boolean?
Default: false
Lazily loaded from lich_settings and cached
Returns the room exits display toggle.
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 |
# File 'documented/lich.rb', line 1188 def self.display_exits if @@display_exits.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_exits';") rescue SQLite3::BusyException sleep 0.1 retry end val = false if val.nil? and XMLData.game != ""; # default false @@display_exits = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil?; end return @@display_exits end |
.display_exits=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the room exits display toggle.
1207 1208 1209 1210 1211 1212 1213 1214 1215 |
# File 'documented/lich.rb', line 1207 def self.display_exits=(val) @@display_exits = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_exits',?);", [@@display_exits.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.display_expgains ⇒ Boolean?
Default: true for non-Genie frontends, false for Genie (which has built-in exp tracking)
Lazily loaded from lich_settings and cached
Returns the experience gains display toggle.
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 |
# File 'documented/lich.rb', line 1331 def self.display_expgains if @@display_expgains.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_expgains';") rescue SQLite3::BusyException sleep 0.1 retry end # Default to true for non-Genie frontends (Genie has built-in exp tracking) # Once explicitly set, the persisted value takes precedence if val.nil? && XMLData.game != "" val = ($frontend == 'genie') ? 'false' : 'true' end @@display_expgains = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil? end @@display_expgains end |
.display_expgains=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the experience gains display toggle.
1354 1355 1356 1357 1358 1359 1360 1361 1362 |
# File 'documented/lich.rb', line 1354 def self.display_expgains=(val) @@display_expgains = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_expgains',?);", [@@display_expgains.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.display_lichid ⇒ Boolean?
Default: true for GemStone, false for DragonRealms
Lazily loaded from lich_settings and cached
Returns the room ID display toggle, defaulting based on game type.
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 |
# File 'documented/lich.rb', line 1013 def self.display_lichid if @@display_lichid.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_lichid';") rescue SQLite3::BusyException sleep 0.1 retry end val = (XMLData.game =~ /^GS/ ? true : false) if val.nil? and XMLData.game != ""; # default false if DR, otherwise default true @@display_lichid = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil?; end return @@display_lichid end |
.display_lichid=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the room ID display toggle.
1032 1033 1034 1035 1036 1037 1038 1039 1040 |
# File 'documented/lich.rb', line 1032 def self.display_lichid=(val) @@display_lichid = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_lichid',?);", [@@display_lichid.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.display_room_links ⇒ Boolean?
Whether room exits are rendered as clickable command links (a
1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 |
# File 'documented/lich.rb', line 1260 def self.display_room_links if @@display_room_links.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_room_links';") rescue SQLite3::BusyException sleep 0.1 retry end val = (XMLData.game =~ /^DR/ ? false : true) if val.nil? and XMLData.game != ""; # default: DR off, others on @@display_room_links = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil?; end return @@display_room_links end |
.display_room_links=(val) ⇒ Boolean, String
Sets and persists the room-exit link toggle.
1278 1279 1280 1281 1282 1283 1284 1285 1286 |
# File 'documented/lich.rb', line 1278 def self.display_room_links=(val) @@display_room_links = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_room_links',?);", [@@display_room_links.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.display_room_mono ⇒ Boolean?
Whether the Lich-injected room lines (Room Number, Room Exits, StringProcs) are wrapped in the fixed-width mono style. Persisted in the lich_settings table and shared across characters. When no value has been saved yet, the default is game-aware: DragonRealms defaults to on (mono, matching the retired roomnumbers.lic look) while GemStone and any other game default to off (the proportional game font, the pre-existing core behavior). The mono wrapper is only emitted on mono-capable frontends (see Frontend.supports_mono?).
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 |
# File 'documented/lich.rb', line 1298 def self.display_room_mono if @@display_room_mono.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_room_mono';") rescue SQLite3::BusyException sleep 0.1 retry end val = (XMLData.game =~ /^DR/ ? true : false) if val.nil? and XMLData.game != ""; # default: DR on, others off @@display_room_mono = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil?; end return @@display_room_mono end |
.display_room_mono=(val) ⇒ Boolean, String
Sets and persists the room-line mono-font toggle.
1316 1317 1318 1319 1320 1321 1322 1323 1324 |
# File 'documented/lich.rb', line 1316 def self.display_room_mono=(val) @@display_room_mono = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_room_mono',?);", [@@display_room_mono.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.display_roomid_location ⇒ String?
Where DragonRealms renders the optional room id / UID chosen via ;display lichid and ;display uid: "title" injects into the room-name line (visible on every front-end), "line" is the historical "Room Number:" line below the room, and "both" does both. GemStone ignores this setting (it always injects into the title line). The value is read fresh from the lich_settings table on first access and then memoized.
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 |
# File 'documented/lich.rb', line 1149 def self.display_roomid_location if @@display_roomid_location.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_roomid_location';") rescue SQLite3::BusyException sleep 0.1 retry end # Default to the historical below-room line once a game is known; leave unresolved # (nil) until then, matching the other display_* getters. val = "line" if val.nil? && XMLData.game != "" @@display_roomid_location = (ROOMID_LOCATIONS.include?(val) ? val : "line") unless val.nil? end return @@display_roomid_location end |
.display_roomid_location=(val) ⇒ void
This method returns an undefined value.
Sets the DragonRealms room-id display placement and persists it. An unrecognized value is ignored (the current setting is retained) so a typo can never blank the display or feed the renderer an invalid placement.
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 |
# File 'documented/lich.rb', line 1170 def self.display_roomid_location=(val) normalized = val.to_s.downcase return unless ROOMID_LOCATIONS.include?(normalized) @@display_roomid_location = normalized begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_roomid_location',?);", [normalized.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.display_stringprocs ⇒ Boolean?
Default: false
Lazily loaded from lich_settings and cached
Returns the StringProcs display toggle.
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 |
# File 'documented/lich.rb', line 1222 def self.display_stringprocs if @@display_stringprocs.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_stringprocs';") rescue SQLite3::BusyException sleep 0.1 retry end val = false if val.nil? and XMLData.game != ""; # default false @@display_stringprocs = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil?; end return @@display_stringprocs end |
.display_stringprocs=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the StringProcs display toggle.
1241 1242 1243 1244 1245 1246 1247 1248 1249 |
# File 'documented/lich.rb', line 1241 def self.display_stringprocs=(val) @@display_stringprocs = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_stringprocs',?);", [@@display_stringprocs.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.display_uid ⇒ Boolean?
Default: true for GemStone, false for DragonRealms
Lazily loaded from lich_settings and cached
Returns the UID (unique ID) display toggle, defaulting based on game type.
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 |
# File 'documented/lich.rb', line 1111 def self.display_uid if @@display_uid.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='display_uid';") rescue SQLite3::BusyException sleep 0.1 retry end val = (XMLData.game =~ /^GS/ ? true : false) if val.nil? and XMLData.game != ""; # default false if DR, otherwise default true @@display_uid = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil?; end return @@display_uid end |
.display_uid=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the UID display toggle.
1130 1131 1132 1133 1134 1135 1136 1137 1138 |
# File 'documented/lich.rb', line 1130 def self.display_uid=(val) @@display_uid = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('display_uid',?);", [@@display_uid.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.find_hosts_file ⇒ String, false
On Windows: queries registry, checks default paths, and searches all drives
On Linux/Mac: checks /etc/hosts and /private/etc/hosts
Stores result in @@hosts_file
Searches the system for the hosts file and caches its path.
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 |
# File 'documented/lich.rb', line 763 def self.find_hosts_file if defined?(Win32) begin key = Win32.RegOpenKeyEx(:hKey => Win32::HKEY_LOCAL_MACHINE, :lpSubKey => 'System\\CurrentControlSet\\Services\\Tcpip\\Parameters', :samDesired => Win32::KEY_READ)[:phkResult] hosts_path = Win32.RegQueryValueEx(:hKey => key, :lpValueName => 'DataBasePath')[:lpData] ensure Win32.RegCloseKey(:hKey => key) rescue nil end if hosts_path windir = (ENV['windir'] || ENV['SYSTEMROOT'] || 'c:\windows') hosts_path.gsub('%SystemRoot%', windir) hosts_file = "#{hosts_path}\\hosts" if File.exist?(hosts_file) return (@@hosts_file = hosts_file) end end if (windir = (ENV['windir'] || ENV['SYSTEMROOT'])) and File.exist?("#{windir}\\system32\\drivers\\etc\\hosts") return (@@hosts_file = "#{windir}\\system32\\drivers\\etc\\hosts") end for drive in ['C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] for windir in ['winnt', 'windows'] if File.exist?("#{drive}:\\#{windir}\\system32\\drivers\\etc\\hosts") return (@@hosts_file = "#{drive}:\\#{windir}\\system32\\drivers\\etc\\hosts") end end end else # Linux/Mac if File.exist?('/etc/hosts') return (@@hosts_file = '/etc/hosts') elsif File.exist?('/private/etc/hosts') return (@@hosts_file = '/private/etc/hosts') end end return (@@hosts_file = false) end |
.fix_game_host_port(gamehost, gameport) ⇒ Array<(String, Integer)>
Maps: gs-plat.simutronics.net:10121 and gs3.simutronics.net:4900 and gs4.simutronics.net:10321 and prime.dr.game.play.net:4901 to current endpoints
Normalizes deprecated game server hostnames and ports to current values.
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 |
# File 'documented/lich.rb', line 933 def self.fix_game_host_port(gamehost, gameport) if (gamehost == 'gs-plat.simutronics.net') and (gameport.to_i == 10121) gamehost = 'storm.gs4.game.play.net' gameport = 10124 elsif (gamehost == 'gs3.simutronics.net') and (gameport.to_i == 4900) gamehost = 'storm.gs4.game.play.net' gameport = 10024 elsif (gamehost == 'gs4.simutronics.net') and (gameport.to_i == 10321) gamehost = 'storm.gs4.game.play.net' gameport = 10324 elsif (gamehost == 'prime.dr.game.play.net') and (gameport.to_i == 4901) gamehost = 'dr.simutronics.net' gameport = 11024 end [gamehost, gameport] end |
.get_simu_launcher ⇒ 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.
Reads from Windows HKEY_LOCAL_MACHINE on Windows; Wine registry on Wine; returns nil on other platforms
Retrieves the path or command of the Simutronics Game Entry (SGE) launcher from the system registry.
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'documented/lich.rb', line 462 def self.get_simu_launcher if defined?(Win32) begin launcher_key = Win32.RegOpenKeyEx(:hKey => Win32::HKEY_LOCAL_MACHINE, :lpSubKey => 'Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command', :samDesired => (Win32::KEY_ALL_ACCESS | Win32::KEY_WOW64_32KEY))[:phkResult] launcher_cmd = Win32.RegQueryValueEx(:hKey => launcher_key, :lpValueName => 'RealCommand')[:lpData] if launcher_cmd.nil? or launcher_cmd.empty? launcher_cmd = Win32.RegQueryValueEx(:hKey => launcher_key)[:lpData] end return launcher_cmd ensure Win32.RegCloseKey(:hKey => launcher_key) rescue nil end elsif defined?(Wine) launcher_cmd = Wine.registry_gets('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\RealCommand') unless launcher_cmd and not launcher_cmd.empty? launcher_cmd = Wine.registry_gets('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\') end return launcher_cmd else return nil end end |
.hide_uid_flag ⇒ Boolean?
Default: false
Lazily loaded from lich_settings and cached
Returns the UID hiding toggle state.
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 |
# File 'documented/lich.rb', line 1047 def self.hide_uid_flag if @@hide_uid_flag.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='hide_uid_flag';") rescue SQLite3::BusyException sleep 0.1 retry end val = false if val.nil? and XMLData.game != ""; # default false @@hide_uid_flag = (val.to_s =~ /on|true|yes/ ? true : false) if !val.nil?; end return @@hide_uid_flag end |
.hide_uid_flag=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the UID hiding toggle state.
1066 1067 1068 1069 1070 1071 1072 1073 1074 |
# File 'documented/lich.rb', line 1066 def self.hide_uid_flag=(val) @@hide_uid_flag = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('hide_uid_flag',?);", [@@hide_uid_flag.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.hosts_file ⇒ String, false
Caches the result in @@hosts_file for subsequent calls
Returns the path to the system hosts file, locating it on first access.
752 753 754 755 |
# File 'documented/lich.rb', line 752 def self.hosts_file Lich.find_hosts_file if @@hosts_file.nil? return @@hosts_file end |
.init_db ⇒ 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.
Creates: script_setting, script_auto_settings, lich_settings, uservars, session_summary_state, session_summary_state indices, trusted_scripts (Ruby 2.0-2.2 only), simu_game_entry, enable_inventory_boxes
Safely handles SQLite3::BusyException and idempotently tolerates duplicate-column errors from migrations
This method returns an undefined value.
Initializes the Lich database schema, creating all required tables and indices.
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'documented/lich.rb', line 277 def self.init_db begin Lich.db.execute("CREATE TABLE IF NOT EXISTS script_setting (script TEXT NOT NULL, name TEXT NOT NULL, value BLOB, PRIMARY KEY(script, name));") Lich.db.execute("CREATE TABLE IF NOT EXISTS script_auto_settings (script TEXT NOT NULL, scope TEXT, hash BLOB, PRIMARY KEY(script, scope));") Lich.db.execute("CREATE TABLE IF NOT EXISTS lich_settings (name TEXT NOT NULL, value TEXT, PRIMARY KEY(name));") Lich.db.execute("CREATE TABLE IF NOT EXISTS uservars (scope TEXT NOT NULL, hash BLOB, PRIMARY KEY(scope));") # Session summary reporting table for process-level heartbeat metadata. # This schema is initialized with the rest of core DB setup to avoid # runtime DDL lock contention on first adapter access. Lich.db.execute("CREATE TABLE IF NOT EXISTS session_summary_state (pid INTEGER PRIMARY KEY, session_name TEXT, role TEXT, state TEXT, frontend TEXT, game_code TEXT, hidden INTEGER DEFAULT 0, started_at INTEGER, last_heartbeat_at INTEGER, os_seen_at INTEGER, os_seen INTEGER, os_name INTEGER, last_utilization_at INTEGER, metadata_json TEXT);") Lich.db.execute("CREATE INDEX IF NOT EXISTS idx_session_summary_state_session_name ON session_summary_state(session_name);") Lich.db.execute("CREATE INDEX IF NOT EXISTS idx_session_summary_state_heartbeat ON session_summary_state(last_heartbeat_at);") # Backward-compatible migration guards: # In dev/test transitions, older local tables may be missing newer columns. # We keep these ALTER blocks idempotent by tolerating duplicate-column errors. begin Lich.db.execute("ALTER TABLE session_summary_state ADD COLUMN os_seen_at INTEGER;") rescue SQLite3::SQLException => e raise unless e..include?('duplicate column name') end begin Lich.db.execute("ALTER TABLE session_summary_state ADD COLUMN os_seen INTEGER;") rescue SQLite3::SQLException => e raise unless e..include?('duplicate column name') end begin Lich.db.execute("ALTER TABLE session_summary_state ADD COLUMN os_name INTEGER;") rescue SQLite3::SQLException => e raise unless e..include?('duplicate column name') end if (RUBY_VERSION =~ /^2\.[012]\./) Lich.db.execute("CREATE TABLE IF NOT EXISTS trusted_scripts (name TEXT NOT NULL);") end Lich.db.execute("CREATE TABLE IF NOT EXISTS simu_game_entry (character TEXT NOT NULL, game_code TEXT NOT NULL, data BLOB, PRIMARY KEY(character, game_code));") Lich.db.execute("CREATE TABLE IF NOT EXISTS enable_inventory_boxes (player_id INTEGER NOT NULL, PRIMARY KEY(player_id));") rescue SQLite3::BusyException sleep 0.1 retry end end |
.inventory_boxes(player_id) ⇒ Boolean
Retries on SQLite3::BusyException
Checks whether inventory boxes are enabled for a given player.
858 859 860 861 862 863 864 865 866 867 868 869 870 |
# File 'documented/lich.rb', line 858 def self.inventory_boxes(player_id) begin v = Lich.db.get_first_value('SELECT player_id FROM enable_inventory_boxes WHERE player_id=?;', [player_id.to_i]) rescue SQLite3::BusyException sleep 0.1 retry end if v true else false end end |
.link_to_sal ⇒ 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.
On Windows non-admin: elevates to admin and re-runs self via ShellExecuteEx
On Wine: modifies the Wine registry for AutoLaunch integration
Saves the original launcher command for later restoration
Integrates Lich into Simutronics AutoLaunch (browser launcher) by modifying the registry.
623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 |
# File 'documented/lich.rb', line 623 def self.link_to_sal if defined?(Win32) if Win32.admin? begin # fixme: 64 bit browsers? launcher_key = Win32.RegOpenKeyEx(:hKey => Win32::HKEY_LOCAL_MACHINE, :lpSubKey => 'Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command', :samDesired => (Win32::KEY_ALL_ACCESS | Win32::KEY_WOW64_32KEY))[:phkResult] r = Win32.RegQueryValueEx(:hKey => launcher_key, :lpValueName => 'RealCommand') if (r[:return] == 0) and not r[:lpData].empty? # already linked return true end r = Win32.GetModuleFileName unless r[:return] > 0 # fixme return false end new_launcher_cmd = "\"#{r[:lpFilename]}\" \"#{File.($PROGRAM_NAME)}\" %1" r = Win32.RegQueryValueEx(:hKey => launcher_key) launcher_cmd = r[:lpData] r = Win32.RegSetValueEx(:hKey => launcher_key, :lpValueName => 'RealCommand', :dwType => Win32::REG_SZ, :lpData => launcher_cmd) return false unless (r == 0) r = Win32.RegSetValueEx(:hKey => launcher_key, :dwType => Win32::REG_SZ, :lpData => new_launcher_cmd) return (r == 0) ensure Win32.RegCloseKey(:hKey => launcher_key) rescue nil end else begin r = Win32.GetModuleFileName file = ((r[:return] > 0) ? r[:lpFilename] : 'rubyw.exe') params = "#{$PROGRAM_NAME.split(/\/|\\/).last} --link-to-sal" r = Win32.ShellExecuteEx(:lpVerb => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params, :fMask => Win32::SEE_MASK_NOCLOSEPROCESS) if r[:return] > 0 process_id = r[:hProcess] sleep 0.2 while Win32.GetExitCodeProcess(:hProcess => process_id)[:lpExitCode] == Win32::STILL_ACTIVE sleep 3 else Win32.ShellExecute(:lpOperation => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params) sleep 6 end rescue Lich.msgbox(:message => $!) end end elsif defined?(Wine) launch_cmd = Wine.registry_gets('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\') return false unless launch_cmd new_launch_cmd = "#{File.($PROGRAM_NAME)} --wine=#{Wine::BIN} --wine-prefix=#{Wine::PREFIX} %1" result = true if launch_cmd if launch_cmd =~ /lich/i $stdout.puts "--- warning: Lich appears to already be installed to the registry" Lich.log "warning: Lich appears to already be installed to the registry" Lich.log 'info: launch_cmd: ' + launch_cmd else result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\RealCommand', launch_cmd) result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\', new_launch_cmd) end end return result else return false end end |
.link_to_sge ⇒ 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.
On Windows non-admin: elevates to admin and re-runs self via ShellExecuteEx
On Wine: modifies the Wine registry for Simutronics launcher integration
Saves the original launcher directory for later restoration
Integrates Lich into the Simutronics Game Entry launcher by modifying the registry.
492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 |
# File 'documented/lich.rb', line 492 def self.link_to_sge if defined?(Win32) if Win32.admin? begin launcher_key = Win32.RegOpenKeyEx(:hKey => Win32::HKEY_LOCAL_MACHINE, :lpSubKey => 'Software\\Simutronics\\Launcher', :samDesired => (Win32::KEY_ALL_ACCESS | Win32::KEY_WOW64_32KEY))[:phkResult] r = Win32.RegQueryValueEx(:hKey => launcher_key, :lpValueName => 'RealDirectory') if (r[:return] == 0) and not r[:lpData].empty? # already linked return true end r = Win32.GetModuleFileName unless r[:return] > 0 # fixme return false end new_launcher_dir = "\"#{r[:lpFilename]}\" \"#{File.($PROGRAM_NAME)}\" " r = Win32.RegQueryValueEx(:hKey => launcher_key, :lpValueName => 'Directory') launcher_dir = r[:lpData] r = Win32.RegSetValueEx(:hKey => launcher_key, :lpValueName => 'RealDirectory', :dwType => Win32::REG_SZ, :lpData => launcher_dir) return false unless (r == 0) r = Win32.RegSetValueEx(:hKey => launcher_key, :lpValueName => 'Directory', :dwType => Win32::REG_SZ, :lpData => new_launcher_dir) return (r == 0) ensure Win32.RegCloseKey(:hKey => launcher_key) rescue nil end else begin r = Win32.GetModuleFileName file = ((r[:return] > 0) ? r[:lpFilename] : 'rubyw.exe') params = "#{$PROGRAM_NAME.split(/\/|\\/).last} --link-to-sge" r = Win32.ShellExecuteEx(:lpVerb => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params, :fMask => Win32::SEE_MASK_NOCLOSEPROCESS) if r[:return] > 0 process_id = r[:hProcess] sleep 0.2 while Win32.GetExitCodeProcess(:hProcess => process_id)[:lpExitCode] == Win32::STILL_ACTIVE sleep 3 else Win32.ShellExecute(:lpOperation => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params) sleep 6 end rescue Lich.msgbox(:message => $!) end end elsif defined?(Wine) launch_dir = Wine.registry_gets('HKEY_LOCAL_MACHINE\\Software\\Simutronics\\Launcher\\Directory') return false unless launch_dir lich_launch_dir = "#{File.($PROGRAM_NAME)} --wine=#{Wine::BIN} --wine-prefix=#{Wine::PREFIX} " result = true if launch_dir if launch_dir =~ /lich/i $stdout.puts "--- warning: Lich appears to already be installed to the registry" Lich.log "warning: Lich appears to already be installed to the registry" Lich.log 'info: launch_dir: ' + launch_dir else result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Simutronics\\Launcher\\RealDirectory', launch_dir) result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Simutronics\\Launcher\\Directory', lich_launch_dir) end end return result else return false end end |
.log(msg) ⇒ void
Format: "YYYY-MM-DD HH:MM:SS: msg"
This method returns an undefined value.
Writes a timestamped message to stderr (the debug log).
341 342 343 |
# File 'documented/lich.rb', line 341 def self.log(msg) $stderr.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}: #{msg}" end |
.max_debug_logs ⇒ Integer
Returns the maximum number of debug log files to retain in the temp
directory. The value is lazily loaded from the lich_settings database
table on first access, then cached in a class variable for subsequent
calls. When no persisted value exists, falls back to
MAX_DEBUG_LOGS_DEFAULT.
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 |
# File 'documented/lich.rb', line 1514 def self.max_debug_logs if @@max_debug_logs.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='max_debug_logs';") rescue SQLite3::BusyException sleep 0.1 retry end @@max_debug_logs = val.nil? ? MAX_DEBUG_LOGS_DEFAULT : [val.to_i, MAX_DEBUG_LOGS_MINIMUM].max end @@max_debug_logs end |
.max_debug_logs=(val) ⇒ void
This method returns an undefined value.
Persists the maximum number of debug log files to retain. Values below MAX_DEBUG_LOGS_MINIMUM are clamped to prevent accidental deletion of all logs.
1539 1540 1541 1542 1543 1544 1545 1546 1547 |
# File 'documented/lich.rb', line 1539 def self.max_debug_logs=(val) @@max_debug_logs = [val.to_i, MAX_DEBUG_LOGS_MINIMUM].max begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('max_debug_logs',?);", [@@max_debug_logs.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.method_missing(arg1, arg2 = '') ⇒ Object
Use Vars class instead
Emits a deprecation warning (throttled to once per 5 minutes); scripts should use Vars.* instead
Deprecated delegation to Vars.method_missing for legacy Lich.* variable access.
239 240 241 242 243 244 245 |
# File 'documented/lich.rb', line 239 def self.method_missing(arg1, arg2 = '') if (Time.now.to_i - @@last_warn_deprecated) > 300 respond "--- warning: Lich.* variables will stop working in a future version of Lich. Use Vars.* (offending script: #{Script.current.name || 'unknown'})" @@last_warn_deprecated = Time.now.to_i end Vars.method_missing(arg1, arg2) end |
.modify_hosts(game_host) ⇒ 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.
Backs up the original hosts file to hosts_file.bak and registers an at_exit handler to restore it
Adds a hosts file entry redirecting a game hostname to 127.0.0.1 for local testing.
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
# File 'documented/lich.rb', line 806 def self.modify_hosts(game_host) if Lich.hosts_file and File.exist?(Lich.hosts_file) at_exit { Lich.restore_hosts } Lich.restore_hosts if File.exist?("#{Lich.hosts_file}.bak") return false end begin # copy hosts to hosts.bak File.open("#{Lich.hosts_file}.bak", 'w') { |hb| File.open(Lich.hosts_file) { |h| hb.write(h.read) } } rescue File.unlink("#{Lich.hosts_file}.bak") if File.exist?("#{Lich.hosts_file}.bak") return false end File.open(Lich.hosts_file, 'a') { |f| f.write "\r\n127.0.0.1\t\t#{game_host}" } return true else return false end end |
.module_eval(*_a) ⇒ nil
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.
Stub implementation that prevents dynamic module evaluation.
334 |
# File 'documented/lich.rb', line 334 def self.module_eval(*_a); nil; end |
.msgbox(args) ⇒ Symbol?
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.
Uses Win32 API on Windows, Gtk on Linux/Mac with Gtk, or stdout.puts on text terminals
Displays a modal message box dialog using the native platform GUI or terminal fallback.
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 409 410 411 412 413 414 415 416 417 418 419 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 |
# File 'documented/lich.rb', line 383 def self.msgbox(args) if defined?(Win32) if args[:buttons] == :ok_cancel = Win32::MB_OKCANCEL elsif args[:buttons] == :yes_no = Win32::MB_YESNO else = Win32::MB_OK end if args[:icon] == :error icon = Win32::MB_ICONERROR elsif args[:icon] == :question icon = Win32::MB_ICONQUESTION elsif args[:icon] == :warning icon = Win32::MB_ICONWARNING else icon = 0 end args[:title] ||= "Lich v#{LICH_VERSION}" r = Win32.MessageBox(:lpText => args[:message], :lpCaption => args[:title], :uType => ( | icon)) if r == Win32::IDIOK return :ok elsif r == Win32::IDICANCEL return :cancel elsif r == Win32::IDIYES return :yes elsif r == Win32::IDINO return :no else return nil end elsif defined?(Gtk) if args[:buttons] == :ok_cancel = :ok_cancel elsif args[:buttons] == :yes_no = :yes_no else = :ok end if args[:icon] == :error type = :error elsif args[:icon] == :question type = :question elsif args[:icon] == :warning type = :warning else type = :info end dialog = Gtk::MessageDialog.new(parent: nil, flags: :modal, type: type, buttons: , message: args[:message]) args[:title] ||= "Lich v#{LICH_VERSION}" dialog.title = args[:title] begin # GTK3 returns the response; it does not yield to a block passed to run. response = dialog.run ensure dialog.destroy end if response == Gtk::ResponseType::OK return :ok elsif response == Gtk::ResponseType::CANCEL return :cancel elsif response == Gtk::ResponseType::YES return :yes elsif response == Gtk::ResponseType::NO return :no else return nil end elsif $stdout.isatty $stdout.puts(args[:message]) return nil end end |
.mutex_lock ⇒ 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.
Logs and responds to user on lock errors; safe to call multiple times
This method returns an undefined value.
Acquires the database mutex lock if not already held by the current thread.
209 210 211 212 213 214 215 216 |
# File 'documented/lich.rb', line 209 def self.mutex_lock begin self.db_mutex.lock unless self.db_mutex.owned? rescue StandardError respond "--- Lich: error: Lich.mutex_lock: #{$!}" Lich.log "error: Lich.mutex_lock: #{$!}\n\t#{$!.backtrace.join("\n\t")}" end end |
.mutex_unlock ⇒ 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.
Logs and responds to user on unlock errors; safe to call when not locked
This method returns an undefined value.
Releases the database mutex lock if currently held by the current thread.
223 224 225 226 227 228 229 230 |
# File 'documented/lich.rb', line 223 def self.mutex_unlock begin self.db_mutex.unlock if self.db_mutex.owned? rescue StandardError respond "--- Lich: error: Lich.mutex_unlock: #{$!}" Lich.log "error: Lich.mutex_unlock: #{$!}\n\t#{$!.backtrace.join("\n\t")}" end end |
.open_sequel_sqlite(path) ⇒ Sequel::Database
Sequel does not expose SQLite3's busy_timeout API directly; the PRAGMA is used instead
Opens an SQLite database via the Sequel ORM and sets the busy timeout via PRAGMA.
42 43 44 45 46 47 |
# File 'documented/lich.rb', line 42 def self.open_sequel_sqlite(path) db = Sequel.sqlite(path) # Sequel does not expose sqlite3's busy_timeout API on its database wrapper. db.run("PRAGMA busy_timeout = #{sqlite_busy_timeout_ms.to_i}") db end |
.open_sqlite_db(path) ⇒ SQLite3::Database
Opens or creates an SQLite3 database at the specified path and applies busy timeout configuration.
33 34 35 |
# File 'documented/lich.rb', line 33 def self.open_sqlite_db(path) configure_sqlite_connection(SQLite3::Database.new(path)) end |
.restore_hosts ⇒ 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.
Exits the process with code 1 on restoration error
This method returns an undefined value.
Restores the hosts file from its backup if present.
833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 |
# File 'documented/lich.rb', line 833 def self.restore_hosts if Lich.hosts_file and File.exist?(Lich.hosts_file) begin # fixme: use rename instead? test rename on windows if File.exist?("#{Lich.hosts_file}.bak") File.open("#{Lich.hosts_file}.bak") { |infile| File.open(Lich.hosts_file, 'w') { |outfile| outfile.write(infile.read) } } File.unlink "#{Lich.hosts_file}.bak" end rescue $stdout.puts "--- error: restore_hosts: #{$!}" Lich.log "error: restore_hosts: #{$!}\n\t#{$!.backtrace.join("\n\t")}" exit(1) end end end |
.seek(fe) ⇒ String?
Prefers Lich::Common::FrontendLocator if available; falls back to legacy global variables
Locates the installation directory of a frontend by name.
252 253 254 255 256 257 258 259 260 261 |
# File 'documented/lich.rb', line 252 def self.seek(fe) if defined?(Lich::Common::FrontendLocator) return Lich::Common::FrontendLocator.compatibility_location(fe) end return $wiz_fe_loc if fe =~ /wizard/ return $sf_fe_loc if fe =~ /stormfront/ nil end |
.set_inventory_boxes(player_id, enabled) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Enables or disables inventory boxes for a given player.
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 |
# File 'documented/lich.rb', line 878 def self.set_inventory_boxes(player_id, enabled) if enabled begin Lich.db.execute('INSERT OR REPLACE INTO enable_inventory_boxes values(?);', [player_id.to_i]) rescue SQLite3::BusyException sleep 0.1 retry end else begin Lich.db.execute('DELETE FROM enable_inventory_boxes where player_id=?;', [player_id.to_i]) rescue SQLite3::BusyException sleep 0.1 retry end end nil end |
.show_deprecated_log ⇒ void
This method returns an undefined value.
Displays all recorded deprecation notices to the user via respond().
367 368 369 370 371 |
# File 'documented/lich.rb', line 367 def self.show_deprecated_log @@deprecated_log.each do |msg| respond(msg) end end |
.sqlite_busy_timeout_ms ⇒ Integer
Returns the configured SQLite busy timeout in milliseconds.
13 14 15 |
# File 'documented/lich.rb', line 13 def self.sqlite_busy_timeout_ms DEFAULT_SQLITE_BUSY_TIMEOUT_MS end |
.track_autosort_state ⇒ Boolean
Lazily loaded from lich_settings and cached
Returns the autosort state tracking toggle.
1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 |
# File 'documented/lich.rb', line 1368 def self.track_autosort_state if @@track_autosort_state.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='track_autosort_state';") rescue SQLite3::BusyException sleep 0.1 retry end @@track_autosort_state = (val.to_s =~ /on|true|yes/ ? true : false) end return @@track_autosort_state end |
.track_autosort_state=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the autosort state tracking toggle.
1386 1387 1388 1389 1390 1391 1392 1393 1394 |
# File 'documented/lich.rb', line 1386 def self.track_autosort_state=(val) @@track_autosort_state = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('track_autosort_state',?);", [@@track_autosort_state.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.track_dark_mode ⇒ Boolean
Lazily loaded from lich_settings and cached
Returns the dark mode state tracking toggle.
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 |
# File 'documented/lich.rb', line 1400 def self.track_dark_mode if @@track_dark_mode.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='track_dark_mode';") rescue SQLite3::BusyException sleep 0.1 retry end @@track_dark_mode = (val.to_s =~ /on|true|yes/ ? true : false) end return @@track_dark_mode end |
.track_dark_mode=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the dark mode state tracking toggle.
1418 1419 1420 1421 1422 1423 1424 1425 1426 |
# File 'documented/lich.rb', line 1418 def self.track_dark_mode=(val) @@track_dark_mode = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('track_dark_mode',?);", [@@track_dark_mode.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.track_layout_state ⇒ Boolean
Lazily loaded from lich_settings and cached
Returns the layout state tracking toggle.
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 |
# File 'documented/lich.rb', line 1432 def self.track_layout_state if @@track_layout_state.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='track_layout_state';") rescue SQLite3::BusyException sleep 0.1 retry end @@track_layout_state = (val.to_s =~ /on|true|yes/ ? true : false) end return @@track_layout_state end |
.track_layout_state=(val) ⇒ void
Retries on SQLite3::BusyException
This method returns an undefined value.
Sets and persists the layout state tracking toggle.
1450 1451 1452 1453 1454 1455 1456 1457 1458 |
# File 'documented/lich.rb', line 1450 def self.track_layout_state=(val) @@track_layout_state = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('track_layout_state',?);", [@@track_layout_state.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.track_persistent_launcher_mode ⇒ Boolean
Returns persisted launcher mode state for GUI login flow.
1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 |
# File 'documented/lich.rb', line 1463 def self.track_persistent_launcher_mode if @@track_persistent_launcher_mode.nil? begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='track_persistent_launcher_mode';") rescue SQLite3::BusyException sleep 0.1 retry end @@track_persistent_launcher_mode = (val.to_s =~ /on|true|yes/ ? true : false) end return @@track_persistent_launcher_mode end |
.track_persistent_launcher_mode=(val) ⇒ void
This method returns an undefined value.
Persists launcher mode state for GUI login flow.
1480 1481 1482 1483 1484 1485 1486 1487 1488 |
# File 'documented/lich.rb', line 1480 def self.track_persistent_launcher_mode=(val) @@track_persistent_launcher_mode = (val.to_s =~ /on|true|yes/ ? true : false) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('track_persistent_launcher_mode',?);", [@@track_persistent_launcher_mode.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |
.unlink_from_sal ⇒ 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.
On Windows non-admin: elevates to admin and re-runs self via ShellExecuteEx
On Wine: restores the Wine registry for AutoLaunch
Removes Lich integration from Simutronics AutoLaunch by restoring the original registry.
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 |
# File 'documented/lich.rb', line 698 def self.unlink_from_sal if defined?(Win32) if Win32.admin? begin launcher_key = Win32.RegOpenKeyEx(:hKey => Win32::HKEY_LOCAL_MACHINE, :lpSubKey => 'Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command', :samDesired => (Win32::KEY_ALL_ACCESS | Win32::KEY_WOW64_32KEY))[:phkResult] real_directory = Win32.RegQueryValueEx(:hKey => launcher_key, :lpValueName => 'RealCommand')[:lpData] if real_directory.nil? or real_directory.empty? # not linked return true end r = Win32.RegSetValueEx(:hKey => launcher_key, :dwType => Win32::REG_SZ, :lpData => real_directory) return false unless (r == 0) r = Win32.RegDeleteValue(:hKey => launcher_key, :lpValueName => 'RealCommand') return (r == 0) ensure Win32.RegCloseKey(:hKey => launcher_key) rescue nil end else begin r = Win32.GetModuleFileName file = ((r[:return] > 0) ? r[:lpFilename] : 'rubyw.exe') params = "#{$PROGRAM_NAME.split(/\/|\\/).last} --unlink-from-sal" r = Win32.ShellExecuteEx(:lpVerb => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params, :fMask => Win32::SEE_MASK_NOCLOSEPROCESS) if r[:return] > 0 process_id = r[:hProcess] sleep 0.2 while Win32.GetExitCodeProcess(:hProcess => process_id)[:lpExitCode] == Win32::STILL_ACTIVE sleep 3 else Win32.ShellExecute(:lpOperation => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params) sleep 6 end rescue Lich.msgbox(:message => $!) end end elsif defined?(Wine) real_launch_cmd = Wine.registry_gets('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\RealCommand') result = true if real_launch_cmd and not real_launch_cmd.empty? result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\', real_launch_cmd) result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Classes\\Simutronics.Autolaunch\\Shell\\Open\\command\\RealCommand', '') end return result else return false end end |
.unlink_from_sge ⇒ 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.
On Windows non-admin: elevates to admin and re-runs self via ShellExecuteEx
On Wine: restores the Wine registry for Simutronics launcher
Removes Lich integration from the Simutronics Game Entry launcher by restoring the original registry.
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 |
# File 'documented/lich.rb', line 566 def self.unlink_from_sge if defined?(Win32) if Win32.admin? begin launcher_key = Win32.RegOpenKeyEx(:hKey => Win32::HKEY_LOCAL_MACHINE, :lpSubKey => 'Software\\Simutronics\\Launcher', :samDesired => (Win32::KEY_ALL_ACCESS | Win32::KEY_WOW64_32KEY))[:phkResult] real_directory = Win32.RegQueryValueEx(:hKey => launcher_key, :lpValueName => 'RealDirectory')[:lpData] if real_directory.nil? or real_directory.empty? # not linked return true end r = Win32.RegSetValueEx(:hKey => launcher_key, :lpValueName => 'Directory', :dwType => Win32::REG_SZ, :lpData => real_directory) return false unless (r == 0) r = Win32.RegDeleteValue(:hKey => launcher_key, :lpValueName => 'RealDirectory') return (r == 0) ensure Win32.RegCloseKey(:hKey => launcher_key) rescue nil end else begin r = Win32.GetModuleFileName file = ((r[:return] > 0) ? r[:lpFilename] : 'rubyw.exe') params = "#{$PROGRAM_NAME.split(/\/|\\/).last} --unlink-from-sge" r = Win32.ShellExecuteEx(:lpVerb => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params, :fMask => Win32::SEE_MASK_NOCLOSEPROCESS) if r[:return] > 0 process_id = r[:hProcess] sleep 0.2 while Win32.GetExitCodeProcess(:hProcess => process_id)[:lpExitCode] == Win32::STILL_ACTIVE sleep 3 else Win32.ShellExecute(:lpOperation => 'runas', :lpFile => file, :lpDirectory => LICH_DIR.tr("/", "\\"), :lpParameters => params) sleep 6 end rescue Lich.msgbox(:message => $!) end end elsif defined?(Wine) real_launch_dir = Wine.registry_gets('HKEY_LOCAL_MACHINE\\Software\\Simutronics\\Launcher\\RealDirectory') result = true if real_launch_dir and not real_launch_dir.empty? result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Simutronics\\Launcher\\Directory', real_launch_dir) result = result && Wine.registry_puts('HKEY_LOCAL_MACHINE\\Software\\Simutronics\\Launcher\\RealDirectory', '') end return result else return false end end |
.win32_launch_method ⇒ 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.
Retries on SQLite3::BusyException
Retrieves the stored Windows launch method preference from lich_settings.
902 903 904 905 906 907 908 909 910 |
# File 'documented/lich.rb', line 902 def self.win32_launch_method begin val = Lich.db.get_first_value("SELECT value FROM lich_settings WHERE name='win32_launch_method';") rescue SQLite3::BusyException sleep 0.1 retry end val end |
.win32_launch_method=(val) ⇒ 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.
Retries on SQLite3::BusyException
This method returns an undefined value.
Stores a Windows launch method preference in lich_settings.
918 919 920 921 922 923 924 925 |
# File 'documented/lich.rb', line 918 def self.win32_launch_method=(val) begin Lich.db.execute("INSERT OR REPLACE INTO lich_settings(name,value) values('win32_launch_method',?);", [val.to_s.encode('UTF-8')]) rescue SQLite3::BusyException sleep 0.1 retry end end |