Class: Lich::Common::SocketReadHook
- Inherits:
-
Object
- Object
- Lich::Common::SocketReadHook
- Defined in:
- documented/common/socket_read_hook.rb
Overview
Read-only hooks that run immediately after a complete line is read from the game socket, before XML parsing, RawHook, DownstreamHook, or frontend writes. Hooks intentionally run inline, like the existing hook chains, to preserve exact reader-before-parser ordering.
Defined Under Namespace
Classes: Event
Class Method Summary collapse
-
.add(name, action = nil) { ... } ⇒ String
Registers a proc to run on every complete line read from the game socket.
-
.add_daemon_hook(name) { ... } ⇒ String
Registers a hook that persists for the daemon lifetime.
-
.add_script_hook(name) { ... } ⇒ String
Registers a hook that removes itself when the calling script exits.
-
.hook_sources ⇒ Hash<String, String>
Returns a mapping of hook names to the source that registered them.
-
.list ⇒ Array<String>
Returns the names of all registered hooks.
-
.remove(name) ⇒ void
Unregisters a hook by name.
-
.run(server_string, received_at: Time.now, monotonic_received_at: monotonic_now) ⇒ void
Invokes all registered hooks with a newly-read server line.
-
.sources ⇒ void
Prints a formatted table of all registered hooks and their sources to the foreground (via Lich::Messaging.mono).
Class Method Details
.add(name, action = nil) { ... } ⇒ String
Registers a proc to run on every complete line read from the game socket.
Hooks run inline before XML parsing and are invoked in registration order. If a hook raises, it is automatically removed and logged; execution continues with the next hook.
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'documented/common/socket_read_hook.rb', line 37 def self.add(name, action = nil, &block) action ||= block unless action.is_a?(Proc) raise ArgumentError, "SocketReadHook: not a Proc (#{action.inspect})" end @@mutex.synchronize do @@hook_sources[name.to_s] = current_source @@hooks[name.to_s] = action end name end |
.add_daemon_hook(name) { ... } ⇒ String
Registers a hook that persists for the daemon lifetime.
Equivalent to .add; provided for API clarity when hooks are added from daemon startup code.
59 60 61 |
# File 'documented/common/socket_read_hook.rb', line 59 def self.add_daemon_hook(name, &block) add(name, &block) end |
.add_script_hook(name) { ... } ⇒ String
Registers a hook that removes itself when the calling script exits.
Calls .before_dying to schedule hook removal on script termination. No-op if before_dying is not available (e.g., in non-script contexts).
72 73 74 75 76 |
# File 'documented/common/socket_read_hook.rb', line 72 def self.add_script_hook(name, &block) add(name, &block) { remove(name) } if defined?() name end |
.hook_sources ⇒ Hash<String, String>
Returns a mapping of hook names to the source that registered them.
Source is the current script name, or 'core' for daemon/core hooks, or 'Unknown' if the source could not be determined.
104 105 106 |
# File 'documented/common/socket_read_hook.rb', line 104 def self.hook_sources @@mutex.synchronize { @@hook_sources.dup } end |
.list ⇒ Array<String>
Returns the names of all registered hooks.
94 95 96 |
# File 'documented/common/socket_read_hook.rb', line 94 def self.list @@mutex.synchronize { @@hooks.keys.dup } end |
.remove(name) ⇒ void
This method returns an undefined value.
Unregisters a hook by name.
Safe to call on non-existent hook names; no error is raised.
84 85 86 87 88 89 |
# File 'documented/common/socket_read_hook.rb', line 84 def self.remove(name) @@mutex.synchronize do @@hook_sources.delete(name.to_s) @@hooks.delete(name.to_s) end end |
.run(server_string, received_at: Time.now, monotonic_received_at: monotonic_now) ⇒ void
Intended to be called only by the socket reader, immediately after parsing a newline.
This method returns an undefined value.
Invokes all registered hooks with a newly-read server line.
Hooks are run synchronously and in-order. The server_string argument is frozen before passing to hooks to prevent accidental mutation. If any hook raises an exception, that hook is removed, the error is logged, and execution continues with the next hook.
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'documented/common/socket_read_hook.rb', line 133 def self.run(server_string, received_at: Time.now, monotonic_received_at: monotonic_now) raw = server_string.dup.freeze event = Event.new( server_string: raw, received_at: received_at, monotonic_received_at: monotonic_received_at ).freeze entries.each do |name, action| invoke(action, raw, event) rescue StandardError => e remove(name) Lich.log "SocketReadHook #{name}: #{e.class}: #{e.}\n\t#{e.backtrace&.first}" end nil end |
.sources ⇒ void
This method returns an undefined value.
Prints a formatted table of all registered hooks and their sources to the foreground (via Lich::Messaging.mono).
Useful for debugging hook registration during development.
114 115 116 117 118 119 |
# File 'documented/common/socket_read_hook.rb', line 114 def self.sources info_table = Terminal::Table.new :headings => ['Hook', 'Source'], :rows => hook_sources.to_a, :style => { :all_separators => true } Lich::Messaging.mono(info_table.to_s) end |