diff --git a/lib/application_manager/task.rb b/lib/application_manager/task.rb index fb0ff69..0b4f608 100644 --- a/lib/application_manager/task.rb +++ b/lib/application_manager/task.rb @@ -41,6 +41,10 @@ class W3DHub @task_state end + def log(string) + log string if W3DHUB_DEBUG + end + # Start task, inside its own thread # FIXME: Ruby 3 has parallelism now: Use a Ractor to do work on a seperate core to # prevent the UI from locking up while doing computation heavy work, i.e building @@ -201,7 +205,7 @@ class W3DHub packages = [] manifests.reverse.each do |manifest| - puts "#{manifest.game}-#{manifest.type}: #{manifest.version} (#{manifest.base_version})" + log "#{manifest.game}-#{manifest.type}: #{manifest.version} (#{manifest.base_version})" manifest.files.each do |file| @files["#{file.name}:#{manifest.version}"] = file @@ -250,7 +254,11 @@ class W3DHub file_count = manifests.map { |m| m.files.count }.sum processed_files = 0 + folder_exists = File.directory?(path) + manifests.each do |manifest| + break unless folder_exists + manifest.files.each do |file| safe_file_name = file.name.gsub("\\", "/") # Fix borked data -> Data 'cause Windows don't care about capitalization @@ -266,7 +274,7 @@ class W3DHub unless File.exist?(file_path) rejected_files << { file: file, manifest_version: manifest.version } - puts "[#{manifest.version}] File missing: #{file_path}" + log "[#{manifest.version}] File missing: #{file_path}" next end @@ -279,21 +287,20 @@ class W3DHub f.close - pp file if file.checksum.nil? + log file.inspect if file.checksum.nil? if digest.hexdigest.upcase == file.checksum.upcase accepted_files[safe_file_name] = manifest.version - # puts "[#{manifest.version}] Verified file: #{file_path}" + log "[#{manifest.version}] Verified file: #{file_path}" else rejected_files << { file: file, manifest_version: manifest.version } - puts "[#{manifest.version}] File failed Verification: #{file_path}" + log "[#{manifest.version}] File failed Verification: #{file_path}" end end end - puts "#{rejected_files.count} missing or corrupt files" + log "#{rejected_files.count} missing or corrupt files" - # TODO: Filter packages to only the required ones selected_packages = [] selected_packages_hash = {} @@ -310,10 +317,8 @@ class W3DHub end end - # FIXME: Order `selected_packages` like `packages` - # Removed packages that don't need to be fetched or processed - packages.delete_if { |package| !selected_packages.find { |pkg| pkg == package } } + packages.delete_if { |package| !selected_packages.find { |pkg| pkg == package } } if folder_exists packages end @@ -421,7 +426,7 @@ class W3DHub def unpack_packages(packages) path = Cache.install_path(@application, @channel) - puts "Unpacking packages in '#{path}'..." + log "Unpacking packages in '#{path}'..." Cache.create_directories(path, true) @status.operations.clear @@ -468,7 +473,7 @@ class W3DHub update_interface_task_status else - puts "COMMAND FAILED!" + log "COMMAND FAILED!" fail!("Failed to unpack #{package.name}") break @@ -508,7 +513,7 @@ class W3DHub @status.step = :mark_application_installed - puts "#{@app_id} has been installed." + log "#{@app_id} has been installed." end ############# @@ -540,7 +545,7 @@ class W3DHub end def package_fetch(package, &block) - puts "Downloading: #{package.category}:#{package.subcategory}:#{package.name}-#{package.version}" + log "Downloading: #{package.category}:#{package.subcategory}:#{package.name}-#{package.version}" Api.package(package) do |chunk, remaining_bytes, total_bytes| block&.call(chunk, remaining_bytes, total_bytes) @@ -548,7 +553,7 @@ class W3DHub end def verify_package(package, &block) - puts "Verifying: #{package.category}:#{package.subcategory}:#{package.name}-#{package.version}" + log "Verifying: #{package.category}:#{package.subcategory}:#{package.name}-#{package.version}" digest = Digest::SHA256.new path = Cache.package_path(package.category, package.subcategory, package.name, package.version) @@ -559,7 +564,7 @@ class W3DHub operation&.value = "Verifying..." file_size = File.size(path) - puts " File size: #{file_size}" + log " File size: #{file_size}" chunk_size = package.checksum_chunk_size chunks = package.checksum_chunks.size @@ -584,11 +589,11 @@ class W3DHub if Digest::SHA256.new.hexdigest(chunk).upcase == checksum.upcase valid_at = chunk_start + read_length - # puts " Passed chunk: #{chunk_start}" + # log " Passed chunk: #{chunk_start}" # package.partially_valid_at_bytes = valid_at package.partially_valid_at_bytes = chunk_start else - puts " FAILED chunk: #{chunk_start}" + log " FAILED chunk: #{chunk_start}" break end end @@ -602,25 +607,25 @@ class W3DHub end def unpack_package(package, path) - puts " #{package.name}:#{package.version}" + log " #{package.name}:#{package.version}" package_path = Cache.package_path(package.category, package.subcategory, package.name, package.version) - puts " Running #{W3DHub.tar_command} command: #{W3DHub.tar_command} -xf \"#{package_path}\" -C \"#{path}\"" + log " Running #{W3DHub.tar_command} command: #{W3DHub.tar_command} -xf \"#{package_path}\" -C \"#{path}\"" return system("#{W3DHub.tar_command} -xf \"#{package_path}\" -C \"#{path}\"") end def apply_patch(package, path) - puts " #{package.name}:#{package.version}" + log " #{package.name}:#{package.version}" package_path = Cache.package_path(package.category, package.subcategory, package.name, package.version) temp_path = "#{Store.settings[:package_cache_dir]}/temp" manifest_file = package.custom_is_patch Cache.create_directories(temp_path, true) - puts " Running #{W3DHub.tar_command} command: #{W3DHub.tar_command} -xf \"#{package_path}\" -C \"#{temp_path}\"" + log " Running #{W3DHub.tar_command} command: #{W3DHub.tar_command} -xf \"#{package_path}\" -C \"#{temp_path}\"" system("#{W3DHub.tar_command} -xf \"#{package_path}\" -C \"#{temp_path}\"") - puts " Loading #{temp_path}/#{manifest_file.name}.patch..." + log " Loading #{temp_path}/#{manifest_file.name}.patch..." patch_mix = W3DHub::Mixer::Reader.new(file_path: "#{temp_path}/#{manifest_file.name}.patch", ignore_crc_mismatches: false) patch_info = JSON.parse(patch_mix.package.files.find { |f| f.name == ".w3dhub.patch" || f.name == ".bhppatch" }.data, symbolize_names: true) @@ -628,15 +633,15 @@ class W3DHub # Fix borked data -> Data 'cause Windows don't care about capitalization repaired_path = "#{path}/#{manifest_file.name.sub('data', 'Data')}" unless File.exist?(repaired_path) && path - puts " Loading #{repaired_path}..." + log " Loading #{repaired_path}..." target_mix = W3DHub::Mixer::Reader.new(file_path: repaired_path, ignore_crc_mismatches: false) - puts " Removing files..." if patch_info[:removedFiles].size.positive? + log " Removing files..." if patch_info[:removedFiles].size.positive? patch_info[:removedFiles].each do |file| target_mix.package.files.delete_if { |f| f.name == file } end - puts " Adding/Updating files..." if patch_info[:updatedFiles].size.positive? + log " Adding/Updating files..." if patch_info[:updatedFiles].size.positive? patch_info[:updatedFiles].each do |file| patch = patch_mix.package.files.find { |f| f.name == file } target = target_mix.package.files.find { |f| f.name == file } @@ -649,7 +654,7 @@ class W3DHub end - puts " Writing updated #{repaired_path}..." if patch_info[:updatedFiles].size.positive? + log " Writing updated #{repaired_path}..." if patch_info[:updatedFiles].size.positive? W3DHub::Mixer::Writer.new(file_path: repaired_path, package: target_mix.package, memory_buffer: true) FileUtils.remove_dir(temp_path) @@ -666,7 +671,7 @@ class W3DHub # Force data/ to Data/ return true unless File.exist?("#{path}/data") && File.directory?("#{path}/data") - puts " Moving #{path}/data/ to #{path}/Data/" + log " Moving #{path}/data/ to #{path}/Data/" FileUtils.mv(Dir.glob("#{path}/data/**"), "#{path}/Data", force: true) FileUtils.remove_dir("#{path}/data", force: true) diff --git a/lib/application_manager/tasks/uninstaller.rb b/lib/application_manager/tasks/uninstaller.rb index fb72e47..7a38e2e 100644 --- a/lib/application_manager/tasks/uninstaller.rb +++ b/lib/application_manager/tasks/uninstaller.rb @@ -33,9 +33,11 @@ class W3DHub @status.value = "Purging installation folder..." @status.progress = Float::INFINITY + @status.step = :uninstalling_application + path = Cache.install_path(@application, @channel) - puts path + log path # TODO: Do some sanity checking, i.e. DO NOT start launcher if `whoami` returns root, path makes sense, # we're not on Windows trying to uninstall a game likely installed by the official launcher FileUtils.remove_dir(path) @@ -51,7 +53,7 @@ class W3DHub @status.step = :mark_application_uninstalled - puts "#{@app_id} has been uninstalled." + log "#{@app_id} has been uninstalled." end end end diff --git a/lib/background_worker.rb b/lib/background_worker.rb index 291f177..8911bb1 100644 --- a/lib/background_worker.rb +++ b/lib/background_worker.rb @@ -42,7 +42,11 @@ class W3DHub while BackgroundWorker.alive? job = @jobs.shift - job&.do + begin + job&.do + rescue => e + pp e + end sleep 0.1 end diff --git a/lib/cache.rb b/lib/cache.rb index 5f83420..ca2c46a 100644 --- a/lib/cache.rb +++ b/lib/cache.rb @@ -112,7 +112,7 @@ class W3DHub tcp_nodelay: true, headers: headers, body: "data=#{JSON.dump({ category: package.category, subcategory: package.subcategory, name: package.name, version: package.version })}", - chunk_size: 4_000_000, + chunk_size: 50_000, response_block: streamer ) diff --git a/lib/pages/login.rb b/lib/pages/login.rb index 989ac28..2a6edc0 100644 --- a/lib/pages/login.rb +++ b/lib/pages/login.rb @@ -36,29 +36,41 @@ class W3DHub # Do network stuff - Api.on_fiber(:user_login, @username.value, @password.value) do |account| - if account - Store.account = account - Store.settings[:account][:data] = account - Store.settings.save_settings + BackgroundWorker.foreground_job( + lambda do + account = Api.user_login(@username.value, @password.value) + applications = nil - Cache.fetch(account.avatar_uri, true) + if account + Store.account = account + Store.settings[:account][:data] = account + Store.settings.save_settings - populate_account_info - applications = Api.applications - Store.applications = applications if applications + Cache.fetch(account.avatar_uri, true) if account + applications = Api.applications if account + end - page(W3DHub::Pages::Games) - else - # An error occurred, enable account entry - # NOTE: Too many incorrect entries causes lock out (Unknown duration) - @username.enabled = true - @password.enabled = true - btn.enabled = true + [account, applications] + end, + lambda do |result| + account, applications = result - @error_label.value = "Incorrect username or password.\nOr too many failed login attempts, try again in a few minutes." + if account + populate_account_info + Store.applications = applications if applications + + page(W3DHub::Pages::Games) + else + # An error occurred, enable account entry + # NOTE: Too many incorrect entries causes lock out (Unknown duration) + @username.enabled = true + @password.enabled = true + btn.enabled = true + + @error_label.value = "Incorrect username or password.\nOr too many failed login attempts, try again in a few minutes." + end end - end + ) end @error_label = caption "", width: 1.0, text_align: :center, color: 0xff_800000 @@ -101,22 +113,30 @@ class W3DHub Store.settings.save_settings Store.account = nil - applications = Api.applications - Store.applications if applications + BackgroundWorker.foreground_job( + -> { Api.applications }, + lambda do |applications| + if applications + Store.applications = applications + page(W3DHub::Pages::Games) if @host.current_page.is_a?(W3DHub::Pages::Games) + page(W3DHub::Pages::ServerBrowser) if @host.current_page.is_a?(W3DHub::Pages::ServerBrowser) + end - @host.instance_variable_get(:"@account_container").clear do - stack(width: 0.7, height: 1.0) do - # background 0xff_222222 - tagline "#{I18n.t(:"interface.not_logged_in")}", text_wrap: :none + @host.instance_variable_get(:"@account_container").clear do + stack(width: 0.7, height: 1.0) do + # background 0xff_222222 + tagline "#{I18n.t(:"interface.not_logged_in")}", text_wrap: :none - flow(width: 1.0) do - link(I18n.t(:"interface.log_in"), text_size: 16, width: 0.5) { page(W3DHub::Pages::Login) } - link I18n.t(:"interface.register"), text_size: 16, width: 0.49 do - Launchy.open("https://secure.w3dhub.com/forum/index.php?app=core&module=global§ion=register") + flow(width: 1.0) do + link(I18n.t(:"interface.log_in"), text_size: 16, width: 0.5) { page(W3DHub::Pages::Login) } + link I18n.t(:"interface.register"), text_size: 16, width: 0.49 do + Launchy.open("https://secure.w3dhub.com/forum/index.php?app=core&module=global§ion=register") + end + end end end end - end + ) end end end diff --git a/lib/pages/server_browser.rb b/lib/pages/server_browser.rb index ecb2abb..176d319 100644 --- a/lib/pages/server_browser.rb +++ b/lib/pages/server_browser.rb @@ -25,6 +25,7 @@ class W3DHub flow(width: 0.75, height: 1.0) do @filters.each do |app_id, enabled| app = Store.applications.games.find { |a| a.id == app_id.to_s } + next unless app image_path = File.exist?("#{GAME_ROOT_PATH}/media/icons/#{app_id}.png") ? "#{GAME_ROOT_PATH}/media/icons/#{app_id}.png" : "#{GAME_ROOT_PATH}/media/icons/default_icon.png" diff --git a/lib/states/boot.rb b/lib/states/boot.rb index 9ea0131..7141791 100644 --- a/lib/states/boot.rb +++ b/lib/states/boot.rb @@ -34,7 +34,7 @@ class W3DHub end def draw - Gosu.draw_circle(window.width / 2, window.height / 2, @w3dhub_logo.width * Gosu.milliseconds / 1000.0 % 500, 128, 0x44_000000, 32) + Gosu.draw_circle(window.width / 2, window.height / 2, @w3dhub_logo.width * (0.6 + Math.cos(Gosu.milliseconds / 1000.0 * Math::PI).abs * 0.05), 128, 0x44_000000, 32) @w3dhub_logo.draw_rot(window.width / 2, window.height / 2, 32) super @@ -43,7 +43,6 @@ class W3DHub def update super - # @fraction += 1.0 * window.dt @fraction = 1.0 / (@tasks.size / @task_index.to_f) @progressbar.value = @fraction @@ -61,8 +60,6 @@ class W3DHub end def refresh_user_token - p :refresh_user_token - if Store.settings[:account, :data] account = Api::Account.new(Store.settings[:account, :data], {}) @@ -99,8 +96,6 @@ class W3DHub end def service_status - p :service_status - Api.on_fiber(:service_status) do |service_status| @service_status = service_status @@ -119,8 +114,6 @@ class W3DHub end def applications - p :applications - @status_label.value = I18n.t(:"boot.checking_for_updates") Api.on_fiber(:applications) do |applications| @@ -136,8 +129,6 @@ class W3DHub end def app_icons - puts :app_icons - return unless Store.applications packages = [] @@ -146,8 +137,6 @@ class W3DHub end Api.on_fiber(:package_details, packages) do |package_details| - puts "Got response?" - package_details&.each do |package| path = Cache.package_path(package.category, package.subcategory, package.name, package.version) generated_icon_path = "#{GAME_ROOT_PATH}/media/icons/#{package.subcategory}.png" @@ -176,8 +165,6 @@ class W3DHub end def server_list - puts :server_list - @status_label.value = I18n.t(:"server_browser.fetching_server_list") Api.on_fiber(:server_list, 2) do |list| diff --git a/lib/states/interface.rb b/lib/states/interface.rb index a6776a3..cdeb27f 100644 --- a/lib/states/interface.rb +++ b/lib/states/interface.rb @@ -158,6 +158,10 @@ class W3DHub @page.focus end + def current_page + @page + end + def update_server_browser(server) return unless @page.is_a?(Pages::ServerBrowser) diff --git a/w3d_hub_linux_launcher.rb b/w3d_hub_linux_launcher.rb index bc0938d..fcfb0ff 100644 --- a/w3d_hub_linux_launcher.rb +++ b/w3d_hub_linux_launcher.rb @@ -27,6 +27,8 @@ I18n.load_path << Dir[File.expand_path("locales") + "/*.yml"] I18n.default_locale = :en class W3DHub + W3DHUB_DEBUG = ARGV.join.include?("--debug") + GAME_ROOT_PATH = File.expand_path(".", __dir__) CACHE_PATH = "#{GAME_ROOT_PATH}/data/cache" SETTINGS_FILE_PATH = "#{GAME_ROOT_PATH}/data/settings.json"