mirror of
https://github.com/cyberarm/w3d_hub_linux_launcher.git
synced 2026-03-22 04:06:18 +00:00
Compare commits
2 Commits
f2cd26dda3
...
90a1c47389
| Author | SHA1 | Date | |
|---|---|---|---|
| 90a1c47389 | |||
| 782d0f1cb3 |
1
Gemfile
1
Gemfile
@@ -10,7 +10,6 @@ gem "digest-crc"
|
|||||||
gem "ircparser"
|
gem "ircparser"
|
||||||
gem "rexml"
|
gem "rexml"
|
||||||
gem "rubyzip"
|
gem "rubyzip"
|
||||||
gem "websocket-client-simple"
|
|
||||||
gem "win32-process", platforms: [:windows]
|
gem "win32-process", platforms: [:windows]
|
||||||
gem "win32-security", platforms: [:windows]
|
gem "win32-security", platforms: [:windows]
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ class W3DHub
|
|||||||
class Api
|
class Api
|
||||||
class ServerListUpdater
|
class ServerListUpdater
|
||||||
LOG_TAG = "W3DHub::Api::ServerListUpdater".freeze
|
LOG_TAG = "W3DHub::Api::ServerListUpdater".freeze
|
||||||
|
|
||||||
|
TYPE_PING = 6
|
||||||
|
|
||||||
include CyberarmEngine::Common
|
include CyberarmEngine::Common
|
||||||
@@instance = nil
|
@@instance = nil
|
||||||
|
|
||||||
@@ -15,6 +18,7 @@ class W3DHub
|
|||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@auto_reconnect = false
|
@auto_reconnect = false
|
||||||
|
@reconnection_delay = 1
|
||||||
|
|
||||||
@invocation_id = 0
|
@invocation_id = 0
|
||||||
|
|
||||||
@@ -23,16 +27,14 @@ class W3DHub
|
|||||||
end
|
end
|
||||||
|
|
||||||
def run
|
def run
|
||||||
return
|
|
||||||
|
|
||||||
Thread.new do
|
Thread.new do
|
||||||
Sync do |task|
|
Sync do |task|
|
||||||
begin
|
begin
|
||||||
async_connect(task)
|
@auto_reconnect = true
|
||||||
|
|
||||||
while W3DHub::BackgroundWorker.alive?
|
while W3DHub::BackgroundWorker.alive?
|
||||||
async_connect(task) if @auto_reconnect
|
connect if @auto_reconnect
|
||||||
sleep 1
|
sleep @reconnection_delay
|
||||||
end
|
end
|
||||||
rescue => e
|
rescue => e
|
||||||
puts e
|
puts e
|
||||||
@@ -48,39 +50,6 @@ class W3DHub
|
|||||||
@@instance = nil
|
@@instance = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def async_connect(task)
|
|
||||||
@auto_reconnect = false
|
|
||||||
|
|
||||||
logger.debug(LOG_TAG) { "Requesting connection token..." }
|
|
||||||
response = Api.post("/listings/push/v2/negotiate?negotiateVersion=1", Api::DEFAULT_HEADERS, "", :gsh)
|
|
||||||
|
|
||||||
if response.status != 200
|
|
||||||
@auto_reconnect = true
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
data = JSON.parse(response.body, symbolize_names: true)
|
|
||||||
|
|
||||||
@invocation_id = 0 if @invocation_id > 9095
|
|
||||||
id = data[:connectionToken]
|
|
||||||
endpoint = "#{Api::SERVER_LIST_ENDPOINT}/listings/push/v2?id=#{id}"
|
|
||||||
|
|
||||||
logger.debug(LOG_TAG) { "Connecting to websocket..." }
|
|
||||||
|
|
||||||
Async::WebSocket::Client.connect(Async::HTTP::Endpoint.parse(endpoint)) do |connection|
|
|
||||||
logger.debug(LOG_TAG) { "Requesting json protocol, v1..." }
|
|
||||||
async_websocket_send(connection, { protocol: "json", version: 1 }.to_json)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def async_websocket_send(connection, payload)
|
|
||||||
connection.write("#{payload}\x1e")
|
|
||||||
connection.flush
|
|
||||||
end
|
|
||||||
|
|
||||||
def async_websocket_read(connection, payload)
|
|
||||||
end
|
|
||||||
|
|
||||||
def connect
|
def connect
|
||||||
@auto_reconnect = false
|
@auto_reconnect = false
|
||||||
|
|
||||||
@@ -89,9 +58,13 @@ class W3DHub
|
|||||||
|
|
||||||
if response.status != 200
|
if response.status != 200
|
||||||
@auto_reconnect = true
|
@auto_reconnect = true
|
||||||
|
@reconnection_delay = @reconnection_delay * 2
|
||||||
|
@reconnection_delay = 60 if @reconnection_delay > 60
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@reconnection_delay = 1
|
||||||
|
|
||||||
data = JSON.parse(response.body, symbolize_names: true)
|
data = JSON.parse(response.body, symbolize_names: true)
|
||||||
|
|
||||||
@invocation_id = 0 if @invocation_id > 9095
|
@invocation_id = 0 if @invocation_id > 9095
|
||||||
@@ -100,7 +73,7 @@ class W3DHub
|
|||||||
|
|
||||||
logger.debug(LOG_TAG) { "Connecting to websocket..." }
|
logger.debug(LOG_TAG) { "Connecting to websocket..." }
|
||||||
this = self
|
this = self
|
||||||
@ws = WebSocket::Client::Simple.connect(endpoint, headers: Api::DEFAULT_HEADERS) do |ws|
|
@ws = WebSocketClient.new.connect(endpoint, headers: Api::DEFAULT_HEADERS) do |ws|
|
||||||
ws.on(:open) do
|
ws.on(:open) do
|
||||||
logger.debug(LOG_TAG) { "Requesting json protocol, v1..." }
|
logger.debug(LOG_TAG) { "Requesting json protocol, v1..." }
|
||||||
ws.send({ protocol: "json", version: 1 }.to_json + "\x1e")
|
ws.send({ protocol: "json", version: 1 }.to_json + "\x1e")
|
||||||
@@ -115,16 +88,18 @@ class W3DHub
|
|||||||
end
|
end
|
||||||
|
|
||||||
ws.on(:message) do |msg|
|
ws.on(:message) do |msg|
|
||||||
msg = msg.data.split("\x1e").first
|
msg = msg.to_str.split("\x1e").first
|
||||||
|
|
||||||
hash = JSON.parse(msg, symbolize_names: true)
|
hash = JSON.parse(msg, symbolize_names: true)
|
||||||
|
|
||||||
# pp hash if hash[:target] != "ServerStatusChanged" && hash[:type] != 6 && hash[:type] != 3
|
# pp hash if hash[:target] != "ServerStatusChanged" && hash[:type] != 6 && hash[:type] != 3
|
||||||
|
|
||||||
# Send PING(?)
|
# Send PING(?)
|
||||||
if hash.empty? || hash[:type] == 6
|
if hash.empty? || hash[:type] == TYPE_PING
|
||||||
ws.send({ type: 6 }.to_json + "\x1e")
|
ws.send({ type: TYPE_PING }.to_json + "\x1e")
|
||||||
else
|
next
|
||||||
|
end
|
||||||
|
|
||||||
case hash[:type]
|
case hash[:type]
|
||||||
when 1
|
when 1
|
||||||
case hash[:target]
|
case hash[:target]
|
||||||
@@ -132,7 +107,12 @@ class W3DHub
|
|||||||
data = hash[:arguments].first
|
data = hash[:arguments].first
|
||||||
|
|
||||||
this.invocation_id += 1
|
this.invocation_id += 1
|
||||||
out = { "type": 1, "invocationId": "#{this.invocation_id}", "target": "SubscribeToServerStatusUpdates", "arguments": [data[:id], 1] }
|
out = {
|
||||||
|
"type": 1,
|
||||||
|
"invocationId": "#{this.invocation_id}",
|
||||||
|
"target": "SubscribeToServerStatusUpdates",
|
||||||
|
"arguments": [data[:id], 1]
|
||||||
|
}
|
||||||
ws.send(out.to_json + "\x1e")
|
ws.send(out.to_json + "\x1e")
|
||||||
|
|
||||||
BackgroundWorker.foreground_job(
|
BackgroundWorker.foreground_job(
|
||||||
@@ -170,10 +150,9 @@ class W3DHub
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
ws.on(:close) do |e|
|
ws.on(:close) do
|
||||||
logger.error(LOG_TAG) { e }
|
logger.error(LOG_TAG) { "Connection closed." }
|
||||||
this.auto_reconnect = true
|
this.auto_reconnect = true
|
||||||
ws.close
|
ws.close
|
||||||
end
|
end
|
||||||
@@ -218,14 +197,24 @@ class W3DHub
|
|||||||
# unsubscribe from removed servers
|
# unsubscribe from removed servers
|
||||||
removed_servers.each do
|
removed_servers.each do
|
||||||
@invocation_id += 1
|
@invocation_id += 1
|
||||||
out = { "type": 1, "invocationId": "#{@invocation_id}", "target": "SubscribeToServerStatusUpdates", "arguments": [server.id, 0] }
|
out = {
|
||||||
|
"type": 1,
|
||||||
|
"invocationId": "#{@invocation_id}",
|
||||||
|
"target": "SubscribeToServerStatusUpdates",
|
||||||
|
"arguments": [server.id, 0]
|
||||||
|
}
|
||||||
ws.send(out.to_json + "\x1e")
|
ws.send(out.to_json + "\x1e")
|
||||||
end
|
end
|
||||||
|
|
||||||
# subscribe to new servers
|
# subscribe to new servers
|
||||||
new_servers.each do
|
new_servers.each do
|
||||||
@invocation_id += 1
|
@invocation_id += 1
|
||||||
out = { "type": 1, "invocationId": "#{@invocation_id}", "target": "SubscribeToServerStatusUpdates", "arguments": [server.id, 1] }
|
out = {
|
||||||
|
"type": 1,
|
||||||
|
"invocationId": "#{@invocation_id}",
|
||||||
|
"target": "SubscribeToServerStatusUpdates",
|
||||||
|
"arguments": [server.id, 1]
|
||||||
|
}
|
||||||
ws.send(out.to_json + "\x1e")
|
ws.send(out.to_json + "\x1e")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -249,9 +249,17 @@ class W3DHub
|
|||||||
|
|
||||||
return nil unless app_data
|
return nil unless app_data
|
||||||
|
|
||||||
found_server = Store.server_list.select do |server|
|
server_options = Store.server_list.select do |server|
|
||||||
server.game == app_id && server.channel == channel && !server.status.password && server.status.player_count < server.status.max_players
|
server.game == app_id &&
|
||||||
end&.first
|
server.channel == channel &&
|
||||||
|
!server.status.password &&
|
||||||
|
server.status.player_count < server.status.max_players
|
||||||
|
end
|
||||||
|
|
||||||
|
# try to find server with lowest ping and matching version
|
||||||
|
found_server = server_options.find { |server| server.version == app_data[:installed_version] }
|
||||||
|
# try to find server with lowest ping and undefined version
|
||||||
|
found_server ||= server_options.find { |server| server.version == Api::ServerListServer::NO_OR_DEFAULT_VERSION }
|
||||||
|
|
||||||
found_server ? found_server : nil
|
found_server ? found_server : nil
|
||||||
end
|
end
|
||||||
@@ -283,7 +291,7 @@ class W3DHub
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def favorive(app_id, bool)
|
def favorite(app_id, bool)
|
||||||
Store.settings[:favorites] ||= {}
|
Store.settings[:favorites] ||= {}
|
||||||
|
|
||||||
if bool
|
if bool
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ class W3DHub
|
|||||||
flow(width: 1.0, height: 28, padding: 8) do
|
flow(width: 1.0, height: 28, padding: 8) do
|
||||||
para "Favorite", fill: true
|
para "Favorite", fill: true
|
||||||
toggle_button checked: Store.application_manager.favorite?(game.id), height: 18, padding_top: 3, padding_right: 3, padding_bottom: 3, padding_left: 3 do |btn|
|
toggle_button checked: Store.application_manager.favorite?(game.id), height: 18, padding_top: 3, padding_right: 3, padding_bottom: 3, padding_left: 3 do |btn|
|
||||||
Store.application_manager.favorive(game.id, btn.value)
|
Store.application_manager.favorite(game.id, btn.value)
|
||||||
Store.settings.save_settings
|
Store.settings.save_settings
|
||||||
|
|
||||||
populate_games_list
|
populate_games_list
|
||||||
|
|||||||
68
lib/websocket_client.rb
Normal file
68
lib/websocket_client.rb
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
class W3DHub
|
||||||
|
class WebSocketClient
|
||||||
|
def initialize
|
||||||
|
@errored = nil
|
||||||
|
@connection = nil
|
||||||
|
|
||||||
|
@events = {
|
||||||
|
open: nil,
|
||||||
|
message: nil,
|
||||||
|
close: nil,
|
||||||
|
error: nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def connect(endpoint, headers: nil, &block)
|
||||||
|
yield(self)
|
||||||
|
|
||||||
|
Sync do |task|
|
||||||
|
endpoint = Async::HTTP::Endpoint.parse(endpoint, alpn_protocols: Async::HTTP::Protocol::HTTP11.names)
|
||||||
|
|
||||||
|
Async::WebSocket::Client.connect(endpoint, headers: headers) do |connection|
|
||||||
|
@connection = connection
|
||||||
|
|
||||||
|
@events[:open]&.call
|
||||||
|
|
||||||
|
while message = connection.read
|
||||||
|
@events[:message].call(message)
|
||||||
|
end
|
||||||
|
# FIXME: Don't rescue for all ta errors?
|
||||||
|
rescue => error
|
||||||
|
@errored = true
|
||||||
|
@events[:error]&.call(error)
|
||||||
|
ensure
|
||||||
|
@events[:close]&.call unless @errored
|
||||||
|
@connection = nil
|
||||||
|
@errored = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def on(event, &block)
|
||||||
|
raise "Event must be a symbol" unless event.is_a?(Symbol)
|
||||||
|
raise "Unknown event: #{event.inspect}" unless @events.keys.include?(event)
|
||||||
|
raise "No block given for #{event.inspect}" unless block_given?
|
||||||
|
|
||||||
|
@events[event] = block
|
||||||
|
end
|
||||||
|
|
||||||
|
def send(data, type: :text)
|
||||||
|
@connection&.write(data)
|
||||||
|
@connection&.flush
|
||||||
|
end
|
||||||
|
|
||||||
|
def close
|
||||||
|
@connection&.close
|
||||||
|
end
|
||||||
|
|
||||||
|
def open?
|
||||||
|
!closed?
|
||||||
|
end
|
||||||
|
|
||||||
|
def closed?
|
||||||
|
@connection&.closed?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -87,7 +87,6 @@ class W3DHub
|
|||||||
BLACK_IMAGE = Gosu::Image.from_blob(1, 1, "\x00\x00\x00\xff")
|
BLACK_IMAGE = Gosu::Image.from_blob(1, 1, "\x00\x00\x00\xff")
|
||||||
end
|
end
|
||||||
|
|
||||||
require "websocket-client-simple"
|
|
||||||
require "English"
|
require "English"
|
||||||
require "sdl2"
|
require "sdl2"
|
||||||
|
|
||||||
@@ -110,6 +109,7 @@ require_relative "lib/ico"
|
|||||||
require_relative "lib/broadcast_server"
|
require_relative "lib/broadcast_server"
|
||||||
require_relative "lib/hardware_survey"
|
require_relative "lib/hardware_survey"
|
||||||
require_relative "lib/game_settings"
|
require_relative "lib/game_settings"
|
||||||
|
require_relative "lib/websocket_client"
|
||||||
require_relative "lib/background_worker"
|
require_relative "lib/background_worker"
|
||||||
require_relative "lib/application_manager"
|
require_relative "lib/application_manager"
|
||||||
require_relative "lib/application_manager/manifest"
|
require_relative "lib/application_manager/manifest"
|
||||||
|
|||||||
Reference in New Issue
Block a user