diff --git a/Gemfile b/Gemfile index 973ad67..d2d6493 100644 --- a/Gemfile +++ b/Gemfile @@ -4,6 +4,7 @@ gem "base64" gem "excon" gem "cyberarm_engine" gem "sdl2-bindings" +gem "libui" gem "digest-crc" gem "i18n" gem "ircparser" @@ -13,11 +14,14 @@ gem "websocket-client-simple" gem "win32-process", 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] # 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\ folder # group :windows_packaging do # gem "bundler", "~>2.4.3" # gem "rake" -# gem "releasy", github: "cyberarm/releasy" -# end +# gem "ocran" +# gem "releasy"#, path: "../releasy" +# end \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock index e16912d..7eda9c4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,22 +3,20 @@ GEM specs: base64 (0.2.0) concurrent-ruby (1.2.3) - cyberarm_engine (0.24.2) - excon (~> 0.88) + cyberarm_engine (0.24.4) gosu (~> 1.1) - gosu_more_drawables (~> 0.3) digest-crc (0.6.5) rake (>= 12.0.0, < 14.0.0) event_emitter (0.2.6) excon (0.109.0) - ffi (1.16.3-x64-mingw-ucrt) + ffi (1.16.3) ffi-win32-extensions (1.0.4) ffi gosu (1.4.6) - gosu_more_drawables (0.3.1) i18n (1.14.1) concurrent-ruby (~> 1.0) ircparser (1.0.0) + libui (0.0.15) rake (13.1.0) rexml (3.2.6) rubyzip (2.3.2) @@ -41,8 +39,10 @@ DEPENDENCIES base64 cyberarm_engine digest-crc + excon i18n ircparser + libui rexml rubyzip sdl2-bindings diff --git a/lib/api/server_list_updater.rb b/lib/api/server_list_updater.rb index 48bba2b..d6caa18 100644 --- a/lib/api/server_list_updater.rb +++ b/lib/api/server_list_updater.rb @@ -73,18 +73,35 @@ class W3DHub hash = JSON.parse(msg, symbolize_names: true) + # pp hash if hash[:target] != "ServerStatusChanged" && hash[:type] != 6 && hash[:type] != 3 + # Send PING(?) if hash.empty? || hash[:type] == 6 ws.send({ type: 6 }.to_json + "\x1e") else case hash[:type] 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] server = Store.server_list.find { |s| s.id == id } 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 diff --git a/lib/application_manager.rb b/lib/application_manager.rb index 0b19b9e..99b4dc4 100644 --- a/lib/application_manager.rb +++ b/lib/application_manager.rb @@ -201,6 +201,14 @@ class W3DHub 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) if (app_data = installed?(app_id, channel)) install_directory = app_data[:install_directory] @@ -208,8 +216,22 @@ class W3DHub exe_path.gsub!("/", "\\") if W3DHub.windows? 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(' ')}") - Process.detach(pid) + exe = File.basename(exe_path) + 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 diff --git a/lib/pages/server_browser.rb b/lib/pages/server_browser.rb index 026248f..6a7ee0b 100644 --- a/lib/pages/server_browser.rb +++ b/lib/pages/server_browser.rb @@ -231,12 +231,23 @@ class W3DHub return list.first end - def refresh_server_list(server) + def refresh_server_list(server, mode = :update) # :remove @refresh_server_list = Gosu.milliseconds + 3_000 @refresh_server = server if @selected_server&.id == 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 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) server_ping = find_element_by_tag(server_container, :ping) + game_icon.value = game_icon(server) server_name.value = "#{server&.status&.name}" server_channel.value = Store.application_manager.channel_name(server.game, server.channel).to_s 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 @server_list_container.clear do - i = -1 - Store.server_list.each do |server| - next unless @filters[server.game.to_sym] - 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 + create_server_container(server) 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 def populate_server_info(server) diff --git a/lib/states/interface.rb b/lib/states/interface.rb index d7651d5..b65e7f4 100644 --- a/lib/states/interface.rb +++ b/lib/states/interface.rb @@ -71,7 +71,7 @@ class W3DHub stack(width: 1.0, height: 1.0, margin_left: 16, margin_right: 16) do flow(width: 1.0, height: 0.65) do @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 @application_taskbar_progressbar = progress fraction: 0.0, height: 2, width: 1.0 @@ -163,10 +163,10 @@ class W3DHub @page end - def update_server_browser(server) + def update_server_browser(server, mode = :update) return unless @page.is_a?(Pages::ServerBrowser) - @page.refresh_server_list(server) + @page.refresh_server_list(server, mode) end def update_server_ping(server) diff --git a/w3d_hub_linux_launcher.rb b/w3d_hub_linux_launcher.rb index 626634a..a020ade 100644 --- a/w3d_hub_linux_launcher.rb +++ b/w3d_hub_linux_launcher.rb @@ -15,6 +15,7 @@ require "time" require "base64" require "zip" require "excon" +require "libui" class W3DHub W3DHUB_DEBUG = ARGV.join.include?("--debug")