mirror of
https://github.com/cyberarm/w3d_hub_linux_launcher.git
synced 2025-12-15 16:52:34 +00:00
Added libui to gems list to use in future for its open_folder dialogs, improvements to server list updater and server browser to correctly handle unregistering and registering servers
This commit is contained in:
10
Gemfile
10
Gemfile
@@ -4,6 +4,7 @@ gem "base64"
|
|||||||
gem "excon"
|
gem "excon"
|
||||||
gem "cyberarm_engine"
|
gem "cyberarm_engine"
|
||||||
gem "sdl2-bindings"
|
gem "sdl2-bindings"
|
||||||
|
gem "libui"
|
||||||
gem "digest-crc"
|
gem "digest-crc"
|
||||||
gem "i18n"
|
gem "i18n"
|
||||||
gem "ircparser"
|
gem "ircparser"
|
||||||
@@ -13,11 +14,14 @@ gem "websocket-client-simple"
|
|||||||
gem "win32-process", platforms: [:x64_mingw, :mingw]
|
gem "win32-process", platforms: [:x64_mingw, :mingw]
|
||||||
gem "win32-security", platforms: [:x64_mingw, :mingw]
|
gem "win32-security", platforms: [:x64_mingw, :mingw]
|
||||||
|
|
||||||
# Packaging on 3.3.0 is... painful. Using 3.2.0 for now.
|
# PACKAGING NOTES
|
||||||
# bundler 2.5.x doesn't seem to play nice with ocra[n]
|
# bundler 2.5.x doesn't seem to play nice with ocra[n]
|
||||||
# use `bundle _x.y.z_ COMMAND` to use this one...
|
# use `bundle _x.y.z_ COMMAND` to use this one...
|
||||||
|
# NOTE: Releasy needs to be installed as a system gem i.e. `rake install`
|
||||||
|
# NOTE: contents of the `gemhome` folder in the packaged folder need to be moved into the lib/ruby/gems\<RUBY_VERSION> folder
|
||||||
# group :windows_packaging do
|
# group :windows_packaging do
|
||||||
# gem "bundler", "~>2.4.3"
|
# gem "bundler", "~>2.4.3"
|
||||||
# gem "rake"
|
# gem "rake"
|
||||||
# gem "releasy", github: "cyberarm/releasy"
|
# gem "ocran"
|
||||||
# end
|
# gem "releasy"#, path: "../releasy"
|
||||||
|
# end
|
||||||
10
Gemfile.lock
10
Gemfile.lock
@@ -3,22 +3,20 @@ GEM
|
|||||||
specs:
|
specs:
|
||||||
base64 (0.2.0)
|
base64 (0.2.0)
|
||||||
concurrent-ruby (1.2.3)
|
concurrent-ruby (1.2.3)
|
||||||
cyberarm_engine (0.24.2)
|
cyberarm_engine (0.24.4)
|
||||||
excon (~> 0.88)
|
|
||||||
gosu (~> 1.1)
|
gosu (~> 1.1)
|
||||||
gosu_more_drawables (~> 0.3)
|
|
||||||
digest-crc (0.6.5)
|
digest-crc (0.6.5)
|
||||||
rake (>= 12.0.0, < 14.0.0)
|
rake (>= 12.0.0, < 14.0.0)
|
||||||
event_emitter (0.2.6)
|
event_emitter (0.2.6)
|
||||||
excon (0.109.0)
|
excon (0.109.0)
|
||||||
ffi (1.16.3-x64-mingw-ucrt)
|
ffi (1.16.3)
|
||||||
ffi-win32-extensions (1.0.4)
|
ffi-win32-extensions (1.0.4)
|
||||||
ffi
|
ffi
|
||||||
gosu (1.4.6)
|
gosu (1.4.6)
|
||||||
gosu_more_drawables (0.3.1)
|
|
||||||
i18n (1.14.1)
|
i18n (1.14.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
ircparser (1.0.0)
|
ircparser (1.0.0)
|
||||||
|
libui (0.0.15)
|
||||||
rake (13.1.0)
|
rake (13.1.0)
|
||||||
rexml (3.2.6)
|
rexml (3.2.6)
|
||||||
rubyzip (2.3.2)
|
rubyzip (2.3.2)
|
||||||
@@ -41,8 +39,10 @@ DEPENDENCIES
|
|||||||
base64
|
base64
|
||||||
cyberarm_engine
|
cyberarm_engine
|
||||||
digest-crc
|
digest-crc
|
||||||
|
excon
|
||||||
i18n
|
i18n
|
||||||
ircparser
|
ircparser
|
||||||
|
libui
|
||||||
rexml
|
rexml
|
||||||
rubyzip
|
rubyzip
|
||||||
sdl2-bindings
|
sdl2-bindings
|
||||||
|
|||||||
@@ -73,18 +73,35 @@ class W3DHub
|
|||||||
|
|
||||||
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
|
||||||
|
|
||||||
# Send PING(?)
|
# Send PING(?)
|
||||||
if hash.empty? || hash[:type] == 6
|
if hash.empty? || hash[:type] == 6
|
||||||
ws.send({ type: 6 }.to_json + "\x1e")
|
ws.send({ type: 6 }.to_json + "\x1e")
|
||||||
else
|
else
|
||||||
case hash[:type]
|
case hash[:type]
|
||||||
when 1
|
when 1
|
||||||
if hash[:target] == "ServerStatusChanged"
|
case hash[:target]
|
||||||
|
when "ServerRegistered"
|
||||||
|
data = hash[:arguments].first
|
||||||
|
server = ServerListServer.new(data)
|
||||||
|
Store.server_list.push(server)
|
||||||
|
|
||||||
|
when "ServerStatusChanged"
|
||||||
id, data = hash[:arguments]
|
id, data = hash[:arguments]
|
||||||
server = Store.server_list.find { |s| s.id == id }
|
server = Store.server_list.find { |s| s.id == id }
|
||||||
server_updated = server&.update(data)
|
server_updated = server&.update(data)
|
||||||
|
|
||||||
BackgroundWorker.foreground_job(-> {}, ->(result){ States::Interface.instance&.update_server_browser(server) }) if server_updated
|
BackgroundWorker.foreground_job(-> {}, ->(result){ States::Interface.instance&.update_server_browser(server, :update) }) if server_updated
|
||||||
|
|
||||||
|
when "ServerUnregistered"
|
||||||
|
id = hash[:arguments].first
|
||||||
|
server = Store.server_list.find { |s| s.id == id }
|
||||||
|
|
||||||
|
if server
|
||||||
|
Store.server_list.delete(server)
|
||||||
|
BackgroundWorker.foreground_job(-> {}, ->(result){ States::Interface.instance&.update_server_browser(server, :remove) })
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -201,6 +201,14 @@ class W3DHub
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def start_command(path, exe)
|
||||||
|
if W3DHub.windows?
|
||||||
|
"start /D \"#{path}\" /B #{exe}"
|
||||||
|
else
|
||||||
|
"#{path}/#{exe}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def run(app_id, channel, *args)
|
def run(app_id, channel, *args)
|
||||||
if (app_data = installed?(app_id, channel))
|
if (app_data = installed?(app_id, channel))
|
||||||
install_directory = app_data[:install_directory]
|
install_directory = app_data[:install_directory]
|
||||||
@@ -208,8 +216,22 @@ class W3DHub
|
|||||||
exe_path.gsub!("/", "\\") if W3DHub.windows?
|
exe_path.gsub!("/", "\\") if W3DHub.windows?
|
||||||
exe_path.gsub!("\\", "/") if W3DHub.unix?
|
exe_path.gsub!("\\", "/") if W3DHub.unix?
|
||||||
|
|
||||||
pid = Process.spawn("#{dxvk_command(app_id, channel)}#{mangohud_command(app_id, channel)}#{wine_command(app_id, channel)}\"#{exe_path}\" -launcher #{args.join(' ')}")
|
exe = File.basename(exe_path)
|
||||||
Process.detach(pid)
|
path = File.dirname(exe_path)
|
||||||
|
|
||||||
|
attempted = false
|
||||||
|
begin
|
||||||
|
pid = Process.spawn("#{dxvk_command(app_id, channel)}#{mangohud_command(app_id, channel)}#{wine_command(app_id, channel)}#{attempted ? start_command(path, exe) : "\"#{exe_path}\""} -launcher #{args.join(' ')}")
|
||||||
|
Process.detach(pid)
|
||||||
|
rescue Errno::EINVAL => e
|
||||||
|
retryable = !attempted
|
||||||
|
attempted = true
|
||||||
|
|
||||||
|
# Assume that we're on windoze and that the game requires admin
|
||||||
|
retry if retryable
|
||||||
|
|
||||||
|
# TODO: Show an error message if we reach here...
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -231,12 +231,23 @@ class W3DHub
|
|||||||
return list.first
|
return list.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def refresh_server_list(server)
|
def refresh_server_list(server, mode = :update) # :remove
|
||||||
@refresh_server_list = Gosu.milliseconds + 3_000
|
@refresh_server_list = Gosu.milliseconds + 3_000
|
||||||
@refresh_server = server if @selected_server&.id == server.id
|
@refresh_server = server if @selected_server&.id == server.id
|
||||||
|
|
||||||
server_container = find_element_by_tag(@server_list_container, server.id)
|
server_container = find_element_by_tag(@server_list_container, server.id)
|
||||||
|
|
||||||
|
case mode
|
||||||
|
when :update
|
||||||
|
if server.status && !server_container
|
||||||
|
@server_list_container.append do
|
||||||
|
create_server_container(server)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
when :remove
|
||||||
|
@server_list_container.remove(server_container) if server_container
|
||||||
|
return
|
||||||
|
end
|
||||||
return unless server_container
|
return unless server_container
|
||||||
|
|
||||||
game_icon = find_element_by_tag(server_container, :game_icon)
|
game_icon = find_element_by_tag(server_container, :game_icon)
|
||||||
@@ -247,6 +258,7 @@ class W3DHub
|
|||||||
player_count = find_element_by_tag(server_container, :player_count)
|
player_count = find_element_by_tag(server_container, :player_count)
|
||||||
server_ping = find_element_by_tag(server_container, :ping)
|
server_ping = find_element_by_tag(server_container, :ping)
|
||||||
|
|
||||||
|
game_icon.value = game_icon(server)
|
||||||
server_name.value = "<b>#{server&.status&.name}</b>"
|
server_name.value = "<b>#{server&.status&.name}</b>"
|
||||||
server_channel.value = Store.application_manager.channel_name(server.game, server.channel).to_s
|
server_channel.value = Store.application_manager.channel_name(server.game, server.channel).to_s
|
||||||
server_region.value = server.region
|
server_region.value = server.region
|
||||||
@@ -299,66 +311,67 @@ class W3DHub
|
|||||||
Store.server_list = Store.server_list.sort_by! { |s| [s&.status&.player_count, s&.id] }.reverse if Store.server_list
|
Store.server_list = Store.server_list.sort_by! { |s| [s&.status&.player_count, s&.id] }.reverse if Store.server_list
|
||||||
|
|
||||||
@server_list_container.clear do
|
@server_list_container.clear do
|
||||||
i = -1
|
|
||||||
|
|
||||||
Store.server_list.each do |server|
|
Store.server_list.each do |server|
|
||||||
next unless @filters[server.game.to_sym]
|
create_server_container(server)
|
||||||
next unless server.region == @filter_region || @filter_region == "Any"
|
|
||||||
next unless Store.application_manager.channel_name(server.game, server.channel) # can user access required game and channel for this server?
|
|
||||||
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
server_container = flow(width: 1.0, height: 56, hover: { background: 0xaa_555566 }, active: { background: 0xaa_555588 }, tag: server.id, tip: ping_tip(server)) do
|
|
||||||
background 0x88_333333 if i.even?
|
|
||||||
|
|
||||||
flow(width: 56, height: 1.0, padding: 4) do
|
|
||||||
image game_icon(server), height: 1.0, tag: :game_icon
|
|
||||||
end
|
|
||||||
|
|
||||||
stack(width: 0.45, height: 1.0) do
|
|
||||||
para server&.status&.name, tag: :server_name, font: BOLD_FONT, text_wrap: :none
|
|
||||||
|
|
||||||
flow(width: 1.0, height: 1.0) do
|
|
||||||
para Store.application_manager.channel_name(server.game, server.channel).to_s, width: 172, margin_right: 8, tag: :server_channel
|
|
||||||
para server.region, tag: :server_region
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
flow(fill: true, height: 1.0) do
|
|
||||||
para "#{server&.status&.map}", tag: :server_map
|
|
||||||
end
|
|
||||||
|
|
||||||
flow(width: 0.11, height: 1.0) do
|
|
||||||
para "#{server&.status&.player_count}/#{server&.status&.max_players}", tag: :player_count
|
|
||||||
end
|
|
||||||
|
|
||||||
flow(width: 56, height: 1.0, padding: 4) do
|
|
||||||
image ping_icon(server), height: 1.0, tag: :ping
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def server_container.hit_element?(x, y)
|
|
||||||
self if hit?(x, y)
|
|
||||||
end
|
|
||||||
|
|
||||||
server_container.subscribe(:clicked_left_mouse_button) do
|
|
||||||
stylize_selected_server(server_container)
|
|
||||||
|
|
||||||
@selected_server_container = server_container
|
|
||||||
|
|
||||||
@selected_server = server
|
|
||||||
|
|
||||||
reorder_server_list if @selected_server_container
|
|
||||||
|
|
||||||
BackgroundWorker.foreground_job(
|
|
||||||
-> { fetch_server_details(server) },
|
|
||||||
->(result) { populate_server_info(server) if server == @selected_server }
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
stylize_selected_server(server_container) if server.id == @selected_server&.id
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
reorder_server_list
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_server_container(server)
|
||||||
|
return unless @filters[server.game.to_sym]
|
||||||
|
return unless server.status
|
||||||
|
return unless server.region == @filter_region || @filter_region == "Any"
|
||||||
|
return unless Store.application_manager.channel_name(server.game, server.channel) # can user access required game and channel for this server?
|
||||||
|
|
||||||
|
server_container = flow(width: 1.0, height: 56, hover: { background: 0xaa_555566 }, active: { background: 0xaa_555588 }, tag: server.id, tip: ping_tip(server)) do
|
||||||
|
flow(width: 56, height: 1.0, padding: 4) do
|
||||||
|
image game_icon(server), height: 1.0, tag: :game_icon
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(width: 0.45, height: 1.0) do
|
||||||
|
para server&.status&.name, tag: :server_name, font: BOLD_FONT, text_wrap: :none
|
||||||
|
|
||||||
|
flow(width: 1.0, height: 1.0) do
|
||||||
|
para Store.application_manager.channel_name(server.game, server.channel).to_s, width: 172, margin_right: 8, tag: :server_channel
|
||||||
|
para server.region, tag: :server_region
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(fill: true, height: 1.0) do
|
||||||
|
para "#{server&.status&.map}", tag: :server_map
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(width: 0.11, height: 1.0) do
|
||||||
|
para "#{server&.status&.player_count}/#{server&.status&.max_players}", tag: :player_count
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(width: 56, height: 1.0, padding: 4) do
|
||||||
|
image ping_icon(server), height: 1.0, tag: :ping
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def server_container.hit_element?(x, y)
|
||||||
|
self if hit?(x, y)
|
||||||
|
end
|
||||||
|
|
||||||
|
server_container.subscribe(:clicked_left_mouse_button) do
|
||||||
|
stylize_selected_server(server_container)
|
||||||
|
|
||||||
|
@selected_server_container = server_container
|
||||||
|
|
||||||
|
@selected_server = server
|
||||||
|
|
||||||
|
reorder_server_list if @selected_server_container
|
||||||
|
|
||||||
|
BackgroundWorker.foreground_job(
|
||||||
|
-> { fetch_server_details(server) },
|
||||||
|
->(result) { populate_server_info(server) if server == @selected_server }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
stylize_selected_server(server_container) if server.id == @selected_server&.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def populate_server_info(server)
|
def populate_server_info(server)
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ class W3DHub
|
|||||||
stack(width: 1.0, height: 1.0, margin_left: 16, margin_right: 16) do
|
stack(width: 1.0, height: 1.0, margin_left: 16, margin_right: 16) do
|
||||||
flow(width: 1.0, height: 0.65) do
|
flow(width: 1.0, height: 0.65) do
|
||||||
@application_taskbar_label = para "", fill: true, text_wrap: :none
|
@application_taskbar_label = para "", fill: true, text_wrap: :none
|
||||||
@application_taskbar_status_label = para "", min_width: 0.40, text_align: :right, text_wrap: :none
|
@application_taskbar_status_label = para "", width: 0.4, min_width: 256, text_align: :right, text_wrap: :none
|
||||||
end
|
end
|
||||||
|
|
||||||
@application_taskbar_progressbar = progress fraction: 0.0, height: 2, width: 1.0
|
@application_taskbar_progressbar = progress fraction: 0.0, height: 2, width: 1.0
|
||||||
@@ -163,10 +163,10 @@ class W3DHub
|
|||||||
@page
|
@page
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_server_browser(server)
|
def update_server_browser(server, mode = :update)
|
||||||
return unless @page.is_a?(Pages::ServerBrowser)
|
return unless @page.is_a?(Pages::ServerBrowser)
|
||||||
|
|
||||||
@page.refresh_server_list(server)
|
@page.refresh_server_list(server, mode)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_server_ping(server)
|
def update_server_ping(server)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ require "time"
|
|||||||
require "base64"
|
require "base64"
|
||||||
require "zip"
|
require "zip"
|
||||||
require "excon"
|
require "excon"
|
||||||
|
require "libui"
|
||||||
|
|
||||||
class W3DHub
|
class W3DHub
|
||||||
W3DHUB_DEBUG = ARGV.join.include?("--debug")
|
W3DHUB_DEBUG = ARGV.join.include?("--debug")
|
||||||
|
|||||||
Reference in New Issue
Block a user