From 7a5667a53a3612e6d08d2d2182827cc00baf21e4 Mon Sep 17 00:00:00 2001 From: Cyberarm Date: Thu, 10 Sep 2026 21:36:43 -0500 Subject: [PATCH] Initial work on implementing tasks --- lib/pages/games.rb | 6 +- lib/worker.rb | 26 ++++-- lib/worker/api.rb | 15 ++-- lib/worker/task.rb | 80 ++++++++++++++++++ lib/worker/tasks/install_application.rb | 26 ++++++ lib/worker/w3dhub_api.rb | 35 +++++--- ...{game_cover.png => default_game_cover.png} | Bin media/default_map_preview.png | Bin 0 -> 23236 bytes 8 files changed, 163 insertions(+), 25 deletions(-) rename media/{game_cover.png => default_game_cover.png} (100%) create mode 100644 media/default_map_preview.png diff --git a/lib/pages/games.rb b/lib/pages/games.rb index d9b5274..c2b73be 100644 --- a/lib/pages/games.rb +++ b/lib/pages/games.rb @@ -65,7 +65,7 @@ module W3DHubLauncher @game_content_container.clear do flow(fill: true, height: 1.0, scroll: true, tag: :hi_mom) do |e| @games.each do |app| - image safe_get_image("#{ROOT_PATH}/media/co1oqw.png"), aspect_ratio: 3 / 4.0, width: 1.0 / game_cover_width_ratio(e), margin_left: HALF_PADDING, margin_right: HALF_PADDING, margin_bottom: PADDING, tip: app.name + image safe_get_image("#{ROOT_PATH}/media/default_game_cover.png"), aspect_ratio: 3 / 4.0, width: 1.0 / game_cover_width_ratio(e), margin_left: HALF_PADDING, margin_right: HALF_PADDING, margin_bottom: PADDING, tip: app.name end e.subscribe(:size_changed) do |e| @@ -184,7 +184,9 @@ module W3DHubLauncher elsif @current_app.servicable? # pp @current_app button "Import", enabled: false, tip: "Import existing application installation", fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_LEFT, **CTA_BUTTON_THEME - button "Download", tip: "Download and install application", fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_RIGHT, **CTA_BUTTON_THEME + button "Download", tip: "Download and install application", fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_RIGHT, **CTA_BUTTON_THEME do + Worker::Api.install_application(@current_app.id, @current_channel.id) + end else button "Import", enabled: false, tip: "Import existing application installation", fill: true, height: 1.0, **CTA_BUTTON_THEME end diff --git a/lib/worker.rb b/lib/worker.rb index ff6fef0..a378228 100644 --- a/lib/worker.rb +++ b/lib/worker.rb @@ -8,6 +8,8 @@ module W3DHubLauncher Response = Data.define(:status, :request_id, :result) + attr_reader :w3dhub_api + def initialize end @@ -29,6 +31,7 @@ module W3DHubLauncher def init_server @threads = [] @requests = [] + @tasks = [] @client = nil @@ -369,19 +372,32 @@ module W3DHubLauncher deliver_response(response.result, query) end - def install_application(query) + def task_install_application(query) + application = @w3dhub_api.applications.find { |app| app.id == query.data["app_id"] } + channel = application.channels.find { |chan| chan.id == query.data["channel_id"] } + + @tasks << Task::InstallApplication.new( + request_id: query.request_id, + application: application, + channel: channel, + installed_version: nil, + target_version: channel.version + ) + @tasks.last.start(self) + + Response.new(Request::STATUS_PENDING, query.request_id, CyberarmEngine::Result.new(data: true)) end - def update_application(query) + def task_update_application(query) end - def repair_application(query) + def task_repair_application(query) end - def move_application(query) + def task_move_application(query) end - def uninstall_application(query) + def task_uninstall_application(query) end end end diff --git a/lib/worker/api.rb b/lib/worker/api.rb index 8c120fc..f6607a0 100644 --- a/lib/worker/api.rb +++ b/lib/worker/api.rb @@ -65,31 +65,36 @@ module W3DHubLauncher # request installation of application # # periodically reports progress until completion - def self.install_application(app_id, channel_id) + def self.install_application(app_id, channel_id, &block) + Worker::Request.new(:task_install_application, { app_id: app_id, channel_id: channel_id }, &block) end # request update of application # # periodically reports progress until completion - def self.update_application(app_id, channel_id) + def self.update_application(app_id, channel_id, &block) + Worker::Request.new(:task_update_application, { app_id: app_id, channel_id: channel_id }, &block) end # request repair of application # # periodically reports progress until completion - def self.repair_application(app_id, channel_id) + def self.repair_application(app_id, channel_id, &block) + Worker::Request.new(:task_repair_application, { app_id: app_id, channel_id: channel_id }, &block) end # request relocation of application # # periodically reports progress until completion - def self.move_application(app_id, channel_id) + def self.move_application(app_id, channel_id, target_directory, &block) + Worker::Request.new(:task_move_application, { app_id: app_id, channel_id: channel_id, target_directory: target_directory }, &block) end # request removal of application # # periodically reports progress until completion - def self.uninstall_application(app_id, channel_id) + def self.uninstall_application(app_id, channel_id, &block) + Worker::Request.new(:task_uninstall_application, { app_id: app_id, channel_id: channel_id }, &block) end end end diff --git a/lib/worker/task.rb b/lib/worker/task.rb index 9f16fa5..2977b4f 100644 --- a/lib/worker/task.rb +++ b/lib/worker/task.rb @@ -1,4 +1,84 @@ module W3DHubLauncher class Task + attr_reader :request_id, :application, :channel, :installed_version, :target_version + + def initialize(request_id:, application:, channel:, installed_version:, target_version:) + @request_id = request_id + @application = application + @channel = channel + @installed_version = installed_version + @target_version = target_version + + pp self + + setup + end + + def setup + end + + def start(worker) + @worker = worker + + execute + end + + def fetch_manifests(version = @target_version) + result = fetch_manifest(version) + if result.okay? + pp result + else + pp [:error, result] + end + end + + def fetch_manifest(version) + @worker.w3dhub_api.fetch_package_details([{category: "games", subcategory: @application.id, name: "manifest.xml", version: version }]) + end end end + +def execute_task + show_application_taskbar + + fail_fast + return false if failed? + + fetch_manifests + return false if failed? + + build_package_list + return false if failed? + + remove_deleted_files + return false if failed? + + verify_files + return false if failed? + + fetch_packages + return false if failed? + + verify_packages + return false if failed? + + unpack_packages + return false if failed? + + create_wine_prefix + return false if failed? + + install_dependencies + return false if failed? + + write_paths_ini + return false if failed? + + mark_application_installed + return false if failed? + + sleep 1 + hide_application_taskbar + + true +end diff --git a/lib/worker/tasks/install_application.rb b/lib/worker/tasks/install_application.rb index e69de29..9f359e1 100644 --- a/lib/worker/tasks/install_application.rb +++ b/lib/worker/tasks/install_application.rb @@ -0,0 +1,26 @@ +module W3DHubLauncher + class Task + class InstallApplication < Task + def setup + end + + def execute + # TODO: + # fail_fast + + # fetch manifests for currently installed version + # AND the target version so we can detect files that need to be removed + # between versions + manifests_result = fetch_manifests + abort_task!(manifests_result) unless manifests_result.okay? + + package_list_result = build_package_list(manifests_result) + abort_task!(package_list_result) unless package_list_result.okay? + + # remove_deleted_files + + verify_files + end + end + end +end diff --git a/lib/worker/w3dhub_api.rb b/lib/worker/w3dhub_api.rb index 52d3e7f..0b15d94 100644 --- a/lib/worker/w3dhub_api.rb +++ b/lib/worker/w3dhub_api.rb @@ -6,9 +6,13 @@ module W3DHubLauncher PRIMARY_W3DHUB_API_ENDPOINT = "https://secure.w3dhub.com".freeze ALTERNATIVE_W3DHUB_API_ENDPOINT = "https://backend.w3d.cyberarm.dev".freeze + attr_reader :applications + def initialize @access_token = nil + @applications = [] + @http_clients = {} end @@ -33,7 +37,7 @@ module W3DHubLauncher Sync do |task| task.with_timeout(API_TIMEOUT) do Async::HTTP::Internet.send(method, url, headers, body) do |response| - # pp [method, url, headers, body] + pp [method, url, headers, body, response] if response.success? result.data = response.read else @@ -104,23 +108,31 @@ module W3DHubLauncher primary_result = @access_token ? fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/launcher/1/get-applications") : CyberarmEngine::Result.new(error: true) alternate_result = fetch("#{ALTERNATIVE_W3DHUB_API_ENDPOINT}/apis/launcher/1/get-applications") + single_source = false + # We've failed to retrieve data if primary_result.error? && alternate_result.error? return result # We've only gotten data back from the primary backend elsif primary_result.okay? && alternate_result.error? result.data = primary_result.data - return result + single_source = true # We've only gotten data back from the alternate backend elsif primary_result.error? && alternate_result.okay? result.data = alternate_result.data - return result + single_source = true end - # We've gotten data back from both backends, merge them. - # pp [primary_result, alternate_result] + unless single_source + puts "FIXME: merge applications source" + # We've gotten data back from both backends, merge them. + # pp [primary_result, alternate_result] + + # FIXME: Merge primary and alternate results + end + + @applications = JSON.parse(result.data)["applications"]&.map { |app| W3DHubLauncher::Worker::Api::Application.new(app) } || [] - # FIXME: Merge primary and alternate results result end @@ -140,15 +152,12 @@ module W3DHubLauncher result = CyberarmEngine::Result.new end - def fetch_manifests() - result = CyberarmEngine::Result.new + def fetch_package_details(packages) + body = URI.encode_www_form("data": JSON.dump({ packages: packages })) + fetch("#{@access_token ? PRIMARY_W3DHUB_API_ENDPOINT : ALTERNATIVE_W3DHUB_API_ENDPOINT}/apis/launcher/1/get-package-details", method: :post, body: body, headers: headers(form_encoded: true)) end - def fetch_package_details() - result = CyberarmEngine::Result.new - end - - def fetch_package() + def download_package() download() end end diff --git a/media/game_cover.png b/media/default_game_cover.png similarity index 100% rename from media/game_cover.png rename to media/default_game_cover.png diff --git a/media/default_map_preview.png b/media/default_map_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..a15a2d83bb165d72b9711ca2f4bc88392d91f5b6 GIT binary patch literal 23236 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 BP!a$D literal 0 HcmV?d00001