diff --git a/lib/application_manager.rb b/lib/application_manager.rb
index 1092c4a..80287b5 100644
--- a/lib/application_manager.rb
+++ b/lib/application_manager.rb
@@ -22,7 +22,6 @@ class W3DHub
installer = Installer.new(app_id, channel)
@tasks.push(installer)
- # installer.start
end
def import(app_id, channel, path)
@@ -81,7 +80,7 @@ class W3DHub
end
def installing?(app_id, channel)
- @tasks.find { |t| t.is_a?(Installer) && t.app_id == app_id }
+ @tasks.find { |t| t.is_a?(Installer) && t.app_id == app_id && t.release_channel == channel }
end
# No application tasks are being done
@@ -91,11 +90,27 @@ class W3DHub
# Whether some operation is in progress
def busy?
- @tasks.any? { |t| t.state == :running }
+ current_task
end
def current_task
- @tasks.first#find { |t| t.state == :running }
+ @tasks.find { |t| [:running, :paused].include?(t.state) }
+ end
+
+ def start_next_available_task
+ return unless idle?
+
+ task = @tasks.find { |t| t.state == :not_started }
+ task&.start
+ end
+
+ def task?(type, app_id, channel)
+ @tasks.find do |t|
+ t.type == type &&
+ t.app_id == app_id &&
+ t.release_channel == channel &&
+ [ :not_started, :running, :paused ].include?(t.state)
+ end
end
end
end
diff --git a/lib/application_manager/task.rb b/lib/application_manager/task.rb
index fd5f0b0..62144bd 100644
--- a/lib/application_manager/task.rb
+++ b/lib/application_manager/task.rb
@@ -4,7 +4,8 @@ class W3DHub
include CyberarmEngine::Common
attr_reader :app_id, :release_channel, :application, :channel,
- :total_bytes_to_download, :bytes_downloaded, :packages_to_download
+ :total_bytes_to_download, :bytes_downloaded, :packages_to_download,
+ :manifests
def initialize(app_id, release_channel)
@app_id = app_id
@@ -19,12 +20,18 @@ class W3DHub
@total_bytes_to_download = -1
@bytes_downloaded = -1
+ @manifests = []
+
setup
end
def setup
end
+ def type
+ raise NotImplementedError
+ end
+
def state
@task_state
end
@@ -41,6 +48,9 @@ class W3DHub
@task_state = :failed unless status
@task_state = :complete unless @task_state == :failed
+
+ hide_application_taskbar if @task_state == :failed
+ send_message_dialog(:failure, "Task #{type.inspect} failed for #{@application.name}", @task_failure_reason) if @task_state == :failed
end
end
@@ -85,6 +95,14 @@ class W3DHub
window.main_thread_queue << block
end
+ def send_message_dialog(type, title, message)
+ run_on_main_thread(
+ proc do
+ window.push_state(W3DHub::States::MessageDialog, type: type, title: title, message: message)
+ end
+ )
+ end
+
def update_application_taskbar(message, status, progress)
run_on_main_thread(
proc do
@@ -115,11 +133,9 @@ class W3DHub
###############
def fetch_manifests
- manifests = []
-
if fetch_manifest("games", app_id, "manifest.xml", @channel.current_version)
manifest = load_manifest("games", app_id, "manifest.xml", @channel.current_version)
- manifests << manifest
+ @manifests << manifest
until(manifest.full?)
fetch_manifest("games", app_id, "manifest.xml", manifest.base_version)
@@ -128,7 +144,7 @@ class W3DHub
end
end
- manifests
+ @manifests
end
def build_package_list(manifests)
@@ -140,6 +156,11 @@ class W3DHub
manifest.files.each do |file|
next if file.removed? # No package data
+ if file.patch?
+ fail!("#{@application.name} requires patches. Patching is not yet supported.")
+ break
+ end
+
next if packages.detect do |pkg|
pkg.category == "games" &&
pkg.subcategory == @app_id &&
@@ -235,8 +256,9 @@ class W3DHub
def fetch_manifest(category, subcategory, name, version, &block)
# Check for and integrity of local manifest
+ package = Api.package_details([{ category: category, subcategory: subcategory, name: name, version: version }])
+
if File.exist?(Cache.package_path(category, subcategory, name, version))
- package = Api.package_details([{ category: category, subcategory: subcategory, name: name, version: version }])
verified = verify_package(package)
# download manifest if not valid
diff --git a/lib/application_manager/tasks/installer.rb b/lib/application_manager/tasks/installer.rb
index 1e1bfa8..8af379e 100644
--- a/lib/application_manager/tasks/installer.rb
+++ b/lib/application_manager/tasks/installer.rb
@@ -1,6 +1,10 @@
class W3DHub
class ApplicationManager
class Installer < Task
+ def type
+ :installer
+ end
+
def execute_task
update_application_taskbar("Downloading #{@application.name}...", "Fetching manifests...", 0.0)
manifests = fetch_manifests
diff --git a/lib/page.rb b/lib/page.rb
index 25410ec..eef9942 100644
--- a/lib/page.rb
+++ b/lib/page.rb
@@ -19,6 +19,9 @@ class W3DHub
@host.main_thread_queue
end
+ def update_application_manager_status
+ end
+
def options=(options)
@options = options
end
diff --git a/lib/pages/games.rb b/lib/pages/games.rb
index b14e77e..a08f2b7 100644
--- a/lib/pages/games.rb
+++ b/lib/pages/games.rb
@@ -137,7 +137,8 @@ class W3DHub
button "Single Player", margin_left: 24
else
unless game.id == "ren"
- button "Install", margin_left: 24 do
+ button "Install", margin_left: 24, enabled: !window.application_manager.task?(:installer, game.id, channel.name) do |button|
+ button.enabled = false
window.application_manager.install(game.id, channel.name)
end
end
diff --git a/lib/states/boot.rb b/lib/states/boot.rb
index 061ed87..e9c352e 100644
--- a/lib/states/boot.rb
+++ b/lib/states/boot.rb
@@ -2,6 +2,8 @@ class W3DHub
class States
class Boot < CyberarmEngine::GuiState
def setup
+ theme(W3DHub::THEME)
+
background 0xff_252525
@fraction = 0.0
@@ -18,7 +20,7 @@ class W3DHub
stack(width: 1.0, height: 0.925) do
end
- @progressbar = progress height: 0.025, width: 1.0, fraction_background: 0xff_00acff, border_thickness: 0
+ @progressbar = progress height: 0.025, width: 1.0
flow(width: 1.0, height: 0.05, padding_left: 16, padding_right: 16, padding_bottom: 8, padding_top: 8) do
@status_label = caption "Starting #{NAME}...", width: 0.5
diff --git a/lib/states/interface.rb b/lib/states/interface.rb
index 96bc8cf..b7065f4 100644
--- a/lib/states/interface.rb
+++ b/lib/states/interface.rb
@@ -15,62 +15,7 @@ class W3DHub
@main_thread_queue = []
- theme({
- ToolTip: {
- background: 0xff_dedede,
- color: 0xaa_000000,
- text_size: 18,
- text_border: false,
- text_shadow: false,
- },
- TextBlock: {
- # font: "Inconsolata",
- text_border: false,
- text_shadow: true,
- text_shadow_size: 1,
- text_shadow_color: 0x88_000000,
- },
- EditLine: {
- border_thickness: 2,
- border_color: Gosu::Color::WHITE,
- hover: { color: Gosu::Color::WHITE }
- },
- Link: {
- color: 0xff_cdcdcd,
- hover: {
- color: Gosu::Color::WHITE
- },
- active: {
- color: 0xff_eeeeee
- }
- },
- Button: {
- text_size: 18,
- padding_top: 8,
- padding_left: 32,
- padding_right: 32,
- padding_bottom: 8,
- border_color: Gosu::Color::NONE,
- background: 0xff_00acff,
- hover: {
- background: 0xff_bee6fd
- },
- active: {
- background: 0xff_add5ec
- }
- },
- ToggleButton: {
- padding_left: 8,
- padding_right: 8,
- width: 18,
- image_width: 18,
- checkmark_image: "#{GAME_ROOT_PATH}/media/ui_icons/checkmark.png"
- },
- Progress: {
- fraction_background: 0xff_00acff,
- border_thickness: 0
- }
- })
+ theme(W3DHub::THEME)
stack(width: 1.0, height: 1.0, border_thickness: 1, border_color: 0xff_aaaaaa) do
background 0xff_252525
@@ -227,6 +172,10 @@ class W3DHub
@page.focus
end
+ def update_application_manager_status
+ @page.update_application_manager_status
+ end
+
def show_application_taskbar
@application_taskbar_container.show
end
diff --git a/lib/states/message_dialog.rb b/lib/states/message_dialog.rb
new file mode 100644
index 0000000..67078e8
--- /dev/null
+++ b/lib/states/message_dialog.rb
@@ -0,0 +1,35 @@
+class W3DHub
+ class States
+ class MessageDialog < CyberarmEngine::GuiState
+ def setup
+ window.show_cursor = true
+
+ theme(W3DHub::THEME)
+
+ background 0xee_444444
+
+ stack(width: 1.0, height: 1.0, margin: 128, padding: 8, background: 0xee_222222) do
+ flow(width: 1.0, height: 0.06) do
+ image "#{GAME_ROOT_PATH}/media/ui_icons/warning.png", width: 0.04, align: :center, color: 0xff_ff8800
+
+ tagline "#{@options[:title]}", width: 0.9, text_align: :center
+ end
+
+ para @options[:message], width: 1.0, height: 0.7, padding: 8
+
+ button "Okay", width: 1.0, margin_top: 64 do
+ pop_state
+ end
+ end
+ end
+
+ def draw
+ previous_state&.draw
+
+ Gosu.flush
+
+ super
+ end
+ end
+ end
+end
diff --git a/lib/theme.rb b/lib/theme.rb
new file mode 100644
index 0000000..c438ee9
--- /dev/null
+++ b/lib/theme.rb
@@ -0,0 +1,58 @@
+class W3DHub
+ THEME = {
+ ToolTip: {
+ background: 0xff_dedede,
+ color: 0xaa_000000,
+ text_size: 18,
+ text_border: false,
+ text_shadow: false
+ },
+ TextBlock: {
+ # font: "Inconsolata",
+ text_border: false,
+ text_shadow: true,
+ text_shadow_size: 1,
+ text_shadow_color: 0x88_000000
+ },
+ EditLine: {
+ border_thickness: 2,
+ border_color: Gosu::Color::WHITE,
+ hover: { color: Gosu::Color::WHITE }
+ },
+ Link: {
+ color: 0xff_cdcdcd,
+ hover: {
+ color: Gosu::Color::WHITE
+ },
+ active: {
+ color: 0xff_eeeeee
+ }
+ },
+ Button: {
+ text_size: 18,
+ padding_top: 8,
+ padding_left: 32,
+ padding_right: 32,
+ padding_bottom: 8,
+ border_color: Gosu::Color::NONE,
+ background: 0xff_00acff,
+ hover: {
+ background: 0xff_bee6fd
+ },
+ active: {
+ background: 0xff_add5ec
+ }
+ },
+ ToggleButton: {
+ padding_left: 8,
+ padding_right: 8,
+ width: 18,
+ image_width: 18,
+ checkmark_image: "#{GAME_ROOT_PATH}/media/ui_icons/checkmark.png"
+ },
+ Progress: {
+ fraction_background: 0xff_00acff,
+ border_thickness: 0
+ }
+ }
+end
diff --git a/lib/window.rb b/lib/window.rb
index 0fa8df6..7e9b253 100644
--- a/lib/window.rb
+++ b/lib/window.rb
@@ -14,6 +14,13 @@ class W3DHub
push_state(W3DHub::States::Boot)
end
+ def update
+ super
+
+ @application_manager.start_next_available_task if @application_manager.idle?
+ current_state.update_application_manager_status if current_state.is_a?(States::Interface)
+ end
+
def close
@settings.save_settings
diff --git a/w3dhub.rb b/w3dhub.rb
index 528c419..5b9ed79 100644
--- a/w3dhub.rb
+++ b/w3dhub.rb
@@ -23,6 +23,7 @@ class W3DHub
end
require_relative "lib/version"
+require_relative "lib/theme"
require_relative "lib/common"
require_relative "lib/window"
require_relative "lib/cache"
@@ -36,6 +37,7 @@ require_relative "lib/application_manager/tasks/repairer"
require_relative "lib/application_manager/tasks/importer"
require_relative "lib/states/boot"
require_relative "lib/states/interface"
+require_relative "lib/states/message_dialog"
require_relative "lib/api"
require_relative "lib/api/service_status"