Class: Sc2::Connection
- Inherits:
-
Object
- Object
- Sc2::Connection
- Includes:
- Requests
- Defined in:
- lib/sc2ai/connection.rb,
lib/sc2ai/connection/requests.rb,
lib/sc2ai/connection/status_listener.rb,
lib/sc2ai/connection/connection_listener.rb
Overview
Manages client connection to the Api
Defined Under Namespace
Modules: ConnectionListener, Requests, StatusListener
Instance Attribute Summary collapse
-
#host ⇒ Object
Returns the value of attribute host.
-
#listeners ⇒ Object
readonly
Returns the value of attribute listeners.
-
#port ⇒ Object
Returns the value of attribute port.
-
#status ⇒ Object
readonly
Last known game status, i.e.
-
#websocket ⇒ Object
Returns the value of attribute websocket.
Instance Method Summary collapse
-
#add_listener(listener, klass:) ⇒ void
Add a listener of specific callback type.
-
#close ⇒ void
Closes Connection to client.
-
#connect ⇒ void
Attempts to connect for a period of time, ignoring errors nad performing on_* callbacks.
-
#initialize(host:, port:) ⇒ Connection
constructor
#param [Sc2::CallbackListener] listener.
-
#remove_listener(listener, klass:) ⇒ Object
Removes a listener of specific callback type.
-
#send_request(request) ⇒ Api::Response
——————————————————— Sends a request synchronously and returns Api::Response type.
-
#send_request_and_ignore(request) ⇒ void
Sends and ignores response.
Methods included from Requests
#action, #available_maps, #create_game, #data, #debug, #game_info, #join_game, #leave_game, #observation, #observer_action, #observer_action_camera_move, #ping, #query, #query_abilities, #query_abilities_for_unit_tags, #query_ability_ids_for_unit, #query_pathings, #query_placements, #quit, #replay_info, #request_quick_load, #request_quick_save, #restart_game, #save_map, #save_replay, #send_request_for, #start_replay, #step
Constructor Details
#initialize(host:, port:) ⇒ Connection
#param [Sc2::CallbackListener] listener
34 35 36 37 38 39 40 41 42 43 |
# File 'lib/sc2ai/connection.rb', line 34 def initialize(host:, port:) @host = host @port = port @listeners = {} @websocket = nil @status = :unknown # Only allow one request at a time. # TODO: Since it turns out the client websocket can only handle 1 request at a time, we don't stricly need Async @scheduler = Async::Semaphore.new(1) end |
Instance Attribute Details
#host ⇒ Object
Returns the value of attribute host.
14 15 16 |
# File 'lib/sc2ai/connection.rb', line 14 def host @host end |
#listeners ⇒ Object
Returns the value of attribute listeners.
29 30 31 |
# File 'lib/sc2ai/connection.rb', line 29 def listeners @listeners end |
#port ⇒ Object
Returns the value of attribute port.
14 15 16 |
# File 'lib/sc2ai/connection.rb', line 14 def port @port end |
#status ⇒ Object
Last known game status, i.e. :launched, :ended, :unknown
:launched // Game has been launch and is not yet doing anything.
:init_game // Create game has been called, and the host is awaiting players.
:in_game // In a single or multiplayer game.
:in_replay // In a replay.
:ended // Game has ended, can still request game info, but ready for a new game.
:quit // Application is shutting down.
:unknown // Should not happen, but indicates an error if it occurs.
@return [Symbol] game status
25 26 27 |
# File 'lib/sc2ai/connection.rb', line 25 def status @status end |
#websocket ⇒ Object
Returns the value of attribute websocket.
14 15 16 |
# File 'lib/sc2ai/connection.rb', line 14 def websocket @websocket end |
Instance Method Details
#add_listener(listener, klass:) ⇒ void
This method returns an undefined value.
Add a listener of specific callback type
81 82 83 84 |
# File 'lib/sc2ai/connection.rb', line 81 def add_listener(listener, klass:) @listeners[klass.to_s] ||= [] @listeners[klass.to_s].push(listener) end |
#close ⇒ void
This method returns an undefined value.
Closes Connection to client
72 73 74 75 |
# File 'lib/sc2ai/connection.rb', line 72 def close @websocket&.close @listeners[ConnectionListener.name]&.each { _1.on_disconnect(self) } end |
#connect ⇒ void
This method returns an undefined value.
Attempts to connect for a period of time, ignoring errors nad performing on_* callbacks
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/sc2ai/connection.rb', line 47 def connect attempt = 1 Sc2.logger.debug { "Waiting for client..." } if (attempt % 5).zero? begin @websocket = Async::WebSocket::Client.connect(endpoint) # , handler: Sc2::Connection::Connection) @listeners[ConnectionListener.name]&.each { _1.on_connected(self) } # do initial ping to ensure status is set and connection is working response_ping = ping Sc2.logger.debug { "Game version: #{response_ping.game_version}" } rescue Errno::ECONNREFUSED, Errno::ECONNRESET raise Error, "Connection timeout. Max retry exceeded." unless (attempt += 1) < 30 # 30s attempts @listeners[ConnectionListener.name]&.each { _1.on_connection_waiting(self) } sleep(1) retry rescue Error => e Sc2.logger.error "#{e.class}: #{e.}" @listeners[ConnectionListener.name]&.each { _1.on_disconnect(self) } end nil end |
#remove_listener(listener, klass:) ⇒ Object
Removes a listener of specific callback type
89 90 91 |
# File 'lib/sc2ai/connection.rb', line 89 def remove_listener(listener, klass:) @listeners[klass.to_s].delete(listener) end |
#send_request(request) ⇒ Api::Response
Sends a request synchronously and returns Api::Response type
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/sc2ai/connection.rb', line 96 def send_request(request) @scheduler.async do |_task| # r = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) #debug # name = request.is_a?(String) ? request : request.request #debug request = request.to_proto unless request.is_a?(String) @websocket.send_binary(request) response = Api::Response.decode(@websocket.read.to_str) if @status != response.status @status = response.status @listeners[StatusListener.name]&.each { _1.on_status_change(@status) } end # Sc2.logger.debug { response } # puts "#{(::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - r) * 1000} - #{name}" #debug response end.wait rescue EOFError => e Sc2.logger.error e close end |
#send_request_and_ignore(request) ⇒ void
This method returns an undefined value.
Sends and ignores response. Meant to be used as optimization for RequestStep. No other command sends and ignores. Expects request to be to_proto’d already
123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/sc2ai/connection.rb', line 123 def send_request_and_ignore(request) @scheduler.async do |_task| @websocket.send_binary(request) while @websocket.read_frame if @websocket.frames.last&.finished? @websocket.frames = [] break end end end.wait nil end |