mirror of
https://github.com/cyberarm/w3d_hub_linux_launcher.git
synced 2025-12-16 17:22:35 +00:00
Added support for applying patches! added DemoInputDelay state to make recording Boot state easier, misc fixes for tweaks.
This commit is contained in:
@@ -51,6 +51,10 @@ class W3DHub
|
|||||||
Thread.new do
|
Thread.new do
|
||||||
status = execute_task
|
status = execute_task
|
||||||
|
|
||||||
|
# Force free some bytes
|
||||||
|
GC.compact if GC.respond_to?(:compact)
|
||||||
|
GC.start
|
||||||
|
|
||||||
@task_state = :failed unless status
|
@task_state = :failed unless status
|
||||||
@task_state = :complete unless @task_state == :failed
|
@task_state = :complete unless @task_state == :failed
|
||||||
|
|
||||||
@@ -221,6 +225,21 @@ class W3DHub
|
|||||||
|
|
||||||
if package_details
|
if package_details
|
||||||
@packages = [package_details].flatten
|
@packages = [package_details].flatten
|
||||||
|
@packages.each do |rich|
|
||||||
|
package = packages.find do |pkg|
|
||||||
|
pkg.category == rich.category &&
|
||||||
|
pkg.subcategory == rich.subcategory &&
|
||||||
|
"#{pkg.name}.zip" == rich.name &&
|
||||||
|
pkg.version == rich.version
|
||||||
|
end
|
||||||
|
|
||||||
|
package.instance_variable_set(:"@name", rich.name)
|
||||||
|
package.instance_variable_set(:"@size", rich.size)
|
||||||
|
package.instance_variable_set(:"@checksum", rich.checksum)
|
||||||
|
package.instance_variable_set(:"@checksum_chunk_size", rich.checksum_chunk_size)
|
||||||
|
package.instance_variable_set(:"@checksum_chunks", rich.checksum_chunks)
|
||||||
|
end
|
||||||
|
|
||||||
@packages_to_download = []
|
@packages_to_download = []
|
||||||
|
|
||||||
@status.label = "Downloading #{@application.name}..."
|
@status.label = "Downloading #{@application.name}..."
|
||||||
@@ -230,7 +249,7 @@ class W3DHub
|
|||||||
package_details.each do |pkg|
|
package_details.each do |pkg|
|
||||||
@status.operations[:"#{pkg.checksum}"] = Status::Operation.new(
|
@status.operations[:"#{pkg.checksum}"] = Status::Operation.new(
|
||||||
label: pkg.name,
|
label: pkg.name,
|
||||||
value: "Verifying...",
|
value: "Pending...",
|
||||||
progress: 0.0
|
progress: 0.0
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@@ -283,7 +302,6 @@ class W3DHub
|
|||||||
puts "FAILED!"
|
puts "FAILED!"
|
||||||
pp package_details
|
pp package_details
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def verify_packages(packages)
|
def verify_packages(packages)
|
||||||
@@ -309,19 +327,26 @@ class W3DHub
|
|||||||
|
|
||||||
@status.step = :unpacking
|
@status.step = :unpacking
|
||||||
|
|
||||||
|
i = -1
|
||||||
packages.each do |package|
|
packages.each do |package|
|
||||||
|
i += 1
|
||||||
|
|
||||||
status = if package.custom_is_patch
|
status = if package.custom_is_patch
|
||||||
@status.operations[:"#{package.checksum}"].value = "Patching..."
|
@status.operations[:"#{package.checksum}"].value = "Patching..."
|
||||||
|
@status.progress = i.to_f / packages.count
|
||||||
update_interface_task_status
|
update_interface_task_status
|
||||||
|
|
||||||
apply_patch(package)
|
apply_patch(package, path)
|
||||||
else
|
else
|
||||||
@status.operations[:"#{package.checksum}"].value = "Unpacking..."
|
@status.operations[:"#{package.checksum}"].value = "Unpacking..."
|
||||||
|
@status.progress = i.to_f / packages.count
|
||||||
update_interface_task_status
|
update_interface_task_status
|
||||||
|
|
||||||
unpack_package(package)
|
unpack_package(package, path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
repair_windows_case_insensitive(package, path)
|
||||||
|
|
||||||
if status
|
if status
|
||||||
@status.operations[:"#{package.checksum}"].value = "Unpacked"
|
@status.operations[:"#{package.checksum}"].value = "Unpacked"
|
||||||
@status.operations[:"#{package.checksum}"].progress = 1.0
|
@status.operations[:"#{package.checksum}"].progress = 1.0
|
||||||
@@ -435,7 +460,7 @@ class W3DHub
|
|||||||
return false unless File.exist?(path)
|
return false unless File.exist?(path)
|
||||||
|
|
||||||
operation = @status.operations[:"#{package.checksum}"]
|
operation = @status.operations[:"#{package.checksum}"]
|
||||||
operation&.value = "Verifying..."
|
operation&.value = "Verifying..."
|
||||||
|
|
||||||
file_size = File.size(path)
|
file_size = File.size(path)
|
||||||
puts " File size: #{file_size}"
|
puts " File size: #{file_size}"
|
||||||
@@ -480,22 +505,74 @@ class W3DHub
|
|||||||
Manifest.new(category, subcategory, name, version)
|
Manifest.new(category, subcategory, name, version)
|
||||||
end
|
end
|
||||||
|
|
||||||
def unpack_package(package)
|
def unpack_package(package, path)
|
||||||
puts " #{package.name}:#{package.version}"
|
puts " #{package.name}:#{package.version}"
|
||||||
package_path = Cache.package_path(package.category, package.subcategory, "#{package.name}.zip", 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}"}"
|
puts " Running #{W3DHub.tar_command} command: #{"#{W3DHub.tar_command} -xf #{package_path} -C #{path}"}"
|
||||||
return system("#{W3DHub.tar_command} -xf #{package_path} -C #{path}")
|
return system("#{W3DHub.tar_command} -xf #{package_path} -C #{path}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def apply_patch(package)
|
def apply_patch(package, path)
|
||||||
# Unpack patch to a known directory
|
puts " #{package.name}:#{package.version}"
|
||||||
# Load MIX1 file
|
package_path = Cache.package_path(package.category, package.subcategory, package.name, package.version)
|
||||||
# Read and Parse .w3dhub.patch json file
|
temp_path = "#{Store.settings[:package_cache_dir]}/temp"
|
||||||
# Load target MIX1 (.mix and .dat)
|
manifest_file = package.custom_is_patch
|
||||||
# Update and remove files
|
|
||||||
# Overwrite updated file
|
Cache.create_directories(temp_path, true)
|
||||||
false
|
|
||||||
|
puts " 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..."
|
||||||
|
patch_mix = W3DHub::Mixer::Reader.new(file_path: "#{temp_path}/#{manifest_file.name}.patch", ignore_crc_mismatches: true, eager_load: true)
|
||||||
|
patch_info = JSON.parse(patch_mix.package.files.find { |f| f.name == ".w3dhub.patch" || f.name == ".bhppatch" }.data, symbolize_names: true)
|
||||||
|
|
||||||
|
repaired_path = "#{path}/#{manifest_file.name}"
|
||||||
|
# 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}..."
|
||||||
|
target_mix = W3DHub::Mixer::Reader.new(file_path: repaired_path, ignore_crc_mismatches: true, eager_load: true)
|
||||||
|
|
||||||
|
puts " 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?
|
||||||
|
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 }
|
||||||
|
|
||||||
|
if target
|
||||||
|
target_mix.package.files[target_mix.package.files.index(target)] = patch
|
||||||
|
else
|
||||||
|
target_mix.package.files << patch
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
puts " 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)
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def repair_windows_case_insensitive(package, path)
|
||||||
|
return true if @app_id == "apb"
|
||||||
|
|
||||||
|
# Force data/ to Data/
|
||||||
|
return true unless File.exist?("#{path}/data") && File.directory?("#{path}/data")
|
||||||
|
|
||||||
|
puts " Moving #{path}/data/ to #{path}/Data/"
|
||||||
|
|
||||||
|
FileUtils.mv(Dir.glob("#{path}/data/**"), "#{path}/Data", force: true)
|
||||||
|
FileUtils.remove_dir("#{path}/data", force: true)
|
||||||
|
|
||||||
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,33 +9,26 @@ class W3DHub
|
|||||||
fail_fast
|
fail_fast
|
||||||
return false if failed?
|
return false if failed?
|
||||||
|
|
||||||
# update_application_taskbar("Downloading #{@application.name}...", "Fetching manifests...", 0.0)
|
|
||||||
manifests = fetch_manifests
|
manifests = fetch_manifests
|
||||||
return false if failed?
|
return false if failed?
|
||||||
|
|
||||||
# update_application_taskbar("Downloading #{@application.name}...", "Building package list...", 0.0)
|
|
||||||
packages = build_package_list(manifests)
|
packages = build_package_list(manifests)
|
||||||
return false if failed?
|
return false if failed?
|
||||||
|
|
||||||
# update_application_taskbar("Downloading #{@application.name}...", "Downloading packages...", 0.0)
|
|
||||||
fetch_packages(packages)
|
fetch_packages(packages)
|
||||||
return false if failed?
|
return false if failed?
|
||||||
|
|
||||||
# update_application_taskbar("Downloading #{@application.name}...", "Verifying packages...", 0.0)
|
|
||||||
verify_packages(packages)
|
verify_packages(packages)
|
||||||
return false if failed?
|
return false if failed?
|
||||||
|
|
||||||
# update_application_taskbar("Installing #{@application.name}...", "Unpacking...", 0.0)
|
|
||||||
unpack_packages(packages)
|
unpack_packages(packages)
|
||||||
return false if failed?
|
return false if failed?
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
# update_application_taskbar("Installing #{@application.name}...", "Creating wine prefix...", 0.0)
|
|
||||||
create_wine_prefix
|
create_wine_prefix
|
||||||
return false if failed?
|
return false if failed?
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
# update_application_taskbar("Installing #{@application.name}...", "Installing dependencies...", 0.0)
|
|
||||||
install_dependencies(packages)
|
install_dependencies(packages)
|
||||||
return false if failed?
|
return false if failed?
|
||||||
sleep 1
|
sleep 1
|
||||||
@@ -43,7 +36,6 @@ class W3DHub
|
|||||||
mark_application_installed
|
mark_application_installed
|
||||||
return false if failed?
|
return false if failed?
|
||||||
|
|
||||||
# update_application_taskbar("Installed #{@application.name}", "", 1.0)
|
|
||||||
sleep 5
|
sleep 5
|
||||||
hide_application_taskbar
|
hide_application_taskbar
|
||||||
|
|
||||||
|
|||||||
12
lib/mixer.rb
12
lib/mixer.rb
@@ -1,4 +1,5 @@
|
|||||||
require "digest"
|
require "digest"
|
||||||
|
require "stringio"
|
||||||
|
|
||||||
class W3DHub
|
class W3DHub
|
||||||
|
|
||||||
@@ -10,9 +11,9 @@ class W3DHub
|
|||||||
class Reader
|
class Reader
|
||||||
attr_reader :package
|
attr_reader :package
|
||||||
|
|
||||||
def initialize(file_path:, ignore_crc_mismatches: false)
|
def initialize(file_path:, ignore_crc_mismatches: false, eager_load: false)
|
||||||
@package = Package.new
|
@package = Package.new
|
||||||
@file = File.open(file_path)
|
@file = eager_load ? StringIO.new(File.read(file_path)) : File.open(file_path)
|
||||||
|
|
||||||
@file.pos = 0
|
@file.pos = 0
|
||||||
|
|
||||||
@@ -79,10 +80,10 @@ class W3DHub
|
|||||||
class Writer
|
class Writer
|
||||||
attr_reader :package
|
attr_reader :package
|
||||||
|
|
||||||
def initialize(file_path:, package:)
|
def initialize(file_path:, package:, memory_buffer: false)
|
||||||
@package = package
|
@package = package
|
||||||
|
|
||||||
@file = File.open(file_path, "wb")
|
@file = memory_buffer ? StringIO.new : File.open(file_path, "wb")
|
||||||
@file.pos = 0
|
@file.pos = 0
|
||||||
|
|
||||||
@file.write("MIX1")
|
@file.write("MIX1")
|
||||||
@@ -121,7 +122,8 @@ class W3DHub
|
|||||||
write_i32(file_name_offset)
|
write_i32(file_name_offset)
|
||||||
|
|
||||||
@file.pos = 0
|
@file.pos = 0
|
||||||
@file.flush
|
|
||||||
|
File.write(file_path, @file.string) if memory_buffer
|
||||||
ensure
|
ensure
|
||||||
@file&.close
|
@file&.close
|
||||||
end
|
end
|
||||||
|
|||||||
12
lib/states/demo_input_delay.rb
Normal file
12
lib/states/demo_input_delay.rb
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
class W3DHub
|
||||||
|
class States
|
||||||
|
class DemoInputDelay < CyberarmEngine::GameState
|
||||||
|
def button_down(id)
|
||||||
|
return unless id == Gosu::KB_SPACE
|
||||||
|
|
||||||
|
pop_state # Erase self
|
||||||
|
push_state(States::Boot)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -15,6 +15,7 @@ class W3DHub
|
|||||||
I18n.locale = :en
|
I18n.locale = :en
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# push_state(W3DHub::States::DemoInputDelay)
|
||||||
push_state(W3DHub::States::Boot)
|
push_state(W3DHub::States::Boot)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ require_relative "lib/application_manager/tasks/installer"
|
|||||||
require_relative "lib/application_manager/tasks/uninstaller"
|
require_relative "lib/application_manager/tasks/uninstaller"
|
||||||
require_relative "lib/application_manager/tasks/repairer"
|
require_relative "lib/application_manager/tasks/repairer"
|
||||||
require_relative "lib/application_manager/tasks/importer"
|
require_relative "lib/application_manager/tasks/importer"
|
||||||
|
require_relative "lib/states/demo_input_delay"
|
||||||
require_relative "lib/states/boot"
|
require_relative "lib/states/boot"
|
||||||
require_relative "lib/states/interface"
|
require_relative "lib/states/interface"
|
||||||
require_relative "lib/states/message_dialog"
|
require_relative "lib/states/message_dialog"
|
||||||
|
|||||||
Reference in New Issue
Block a user