mirror of
https://github.com/cyberarm/w3d_hub_linux_launcher.git
synced 2026-11-04 00:54:09 +00:00
Compare commits
2 Commits
a7e1378f55
...
f6fbd1bce1
| Author | SHA1 | Date | |
|---|---|---|---|
| f6fbd1bce1 | |||
| c6de24bf34 |
@@ -32,10 +32,12 @@ module W3DHubLauncher
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Downloads requested url and on success check if host element is still in the layout and call the block if so.
|
# Downloads requested url and on success check if host element is still in the layout and call the block if so.
|
||||||
def remote_image(path, url:, element:, &block)
|
def remote_image(path, url:, element:, required_path: nil, &block)
|
||||||
memcache_key = :"lock_net_download_#{element.style.tag}"
|
memcache_key = :"lock_net_download_#{element.style.tag}"
|
||||||
|
|
||||||
if !File.exist?(path) && MemCache[memcache_key].nil?
|
path_exists = File.exist?(path)
|
||||||
|
|
||||||
|
if !path_exists && MemCache[memcache_key].nil?
|
||||||
MemCache[memcache_key] = true
|
MemCache[memcache_key] = true
|
||||||
|
|
||||||
Worker::Api.download_url(url, path) do |result|
|
Worker::Api.download_url(url, path) do |result|
|
||||||
@@ -53,6 +55,14 @@ module W3DHubLauncher
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if required_path && path_exists && !File.exist?(required_path)
|
||||||
|
e = find_element_by_tag(element.root, element.style.tag)
|
||||||
|
|
||||||
|
return unless e
|
||||||
|
|
||||||
|
block.call(element, path)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def on_main_thread(block)
|
def on_main_thread(block)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ module W3DHubLauncher
|
|||||||
def blur
|
def blur
|
||||||
@parent.hide_battleview_panel
|
@parent.hide_battleview_panel
|
||||||
|
|
||||||
CyberarmEngine::EventBus.unsubscribe("application_changed")
|
CyberarmEngine::EventBus.unsubscribe("application_changed", self)
|
||||||
end
|
end
|
||||||
|
|
||||||
def populate_game_content_container
|
def populate_game_content_container
|
||||||
@@ -154,7 +154,7 @@ module W3DHubLauncher
|
|||||||
btn = button(safe_get_image("#{CACHE_PATH}/icon_#{game.id}.png"), tag: :"image_icon_#{game.id}", style_class: [:app_icon_button], enabled: @current_app.id != game.id, tip: game.name) do |btn|
|
btn = button(safe_get_image("#{CACHE_PATH}/icon_#{game.id}.png"), tag: :"image_icon_#{game.id}", style_class: [:app_icon_button], enabled: @current_app.id != game.id, tip: game.name) do |btn|
|
||||||
populate_game(game, game&.channels&.first)
|
populate_game(game, game&.channels&.first)
|
||||||
end
|
end
|
||||||
remote_image("#{CACHE_PATH}/icon_#{game.id}.ico", url: "https://s3.w3d.cyberarm.dev/games/#{game.id}/#{game.id}.ico", element: btn) do |e, path|
|
remote_image("#{CACHE_PATH}/icon_#{game.id}.ico", required_path: "#{CACHE_PATH}/icon_#{game.id}.png", url: "https://s3.w3d.cyberarm.dev/games/#{game.id}/#{game.id}.ico", element: btn) do |e, path|
|
||||||
Worker::Api.ico_to_png(ico_path: path, png_path: path.sub(".ico", ".png")) do |result|
|
Worker::Api.ico_to_png(ico_path: path, png_path: path.sub(".ico", ".png")) do |result|
|
||||||
e&.value = safe_get_image(result.data["path"]) if result.okay?
|
e&.value = safe_get_image(result.data["path"]) if result.okay?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ module W3DHubLauncher
|
|||||||
@sha256_checksum = hash["checksum"]
|
@sha256_checksum = hash["checksum"]
|
||||||
@checksum_chunks = hash["checksum-chunks"]
|
@checksum_chunks = hash["checksum-chunks"]
|
||||||
@download_url = hash["download_url"]
|
@download_url = hash["download_url"]
|
||||||
|
|
||||||
|
# Fix crashing on spaces
|
||||||
|
if @download_url
|
||||||
|
uri_path = @download_url.split("/").last
|
||||||
|
@download_url = @download_url.sub(uri_path, URI.encode_uri_component(uri_path))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def error?
|
def error?
|
||||||
|
|||||||
107
lib/worker/api/verification_data.rb
Normal file
107
lib/worker/api/verification_data.rb
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class Worker
|
||||||
|
class Api
|
||||||
|
|
||||||
|
# Cached verifcation data for application and pending package files
|
||||||
|
class VerificationData
|
||||||
|
SCHEMA = 0
|
||||||
|
|
||||||
|
def initialize(path)
|
||||||
|
@path = path
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
if File.exist?(@path)
|
||||||
|
begin
|
||||||
|
data = JSON.parse(File.read(@path))
|
||||||
|
rescue JSON::ParserError
|
||||||
|
data = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
data = {} unless data.is_a?(Hash)
|
||||||
|
|
||||||
|
@schema = data["schema"] || SCHEMA
|
||||||
|
@data = {}
|
||||||
|
data["data"]&.each do |key, value|
|
||||||
|
@data[key] = Data.new(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def key(file_name, file_version: "", package: false)
|
||||||
|
file_name = file_name.gsub("\\", "/").downcase
|
||||||
|
|
||||||
|
if package
|
||||||
|
"package:{file_name}:#{file_version}"
|
||||||
|
else
|
||||||
|
file_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def data(key)
|
||||||
|
@data[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
def unchanged?(key, checksum:, file_path:)
|
||||||
|
data = data(key)
|
||||||
|
return nil unless data
|
||||||
|
|
||||||
|
return data if data.checksum.upcase.strip == checksum.upcase.strip &&
|
||||||
|
data.modification_time == File.mtime(file_path).to_i &&
|
||||||
|
data.file_size == File.size(file_path)
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def set(key, checksum:, file_path:)
|
||||||
|
data = Data.new(
|
||||||
|
{
|
||||||
|
"checksum" => checksum.upcase.strip,
|
||||||
|
"modification_time" => File.mtime(file_path).to_i,
|
||||||
|
"file_size" => File.size(file_path)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@data[key] = data
|
||||||
|
save
|
||||||
|
|
||||||
|
data
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(key)
|
||||||
|
data = @data.delete(key)
|
||||||
|
save
|
||||||
|
|
||||||
|
data
|
||||||
|
end
|
||||||
|
|
||||||
|
def save
|
||||||
|
File.write(@path, JSON.pretty_generate(self))
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_json(options = {})
|
||||||
|
{
|
||||||
|
schema: SCHEMA,
|
||||||
|
data: @data
|
||||||
|
}.to_json(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
class Data
|
||||||
|
attr_reader :checksum, :modification_time, :file_size
|
||||||
|
|
||||||
|
def initialize(data)
|
||||||
|
@checksum = data["checksum"]
|
||||||
|
@modification_time = data["modification_time"]
|
||||||
|
@file_size = data["file_size"]
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_json(options = {})
|
||||||
|
{
|
||||||
|
checksum: @checksum,
|
||||||
|
modification_time: @modification_time,
|
||||||
|
file_size: @file_size
|
||||||
|
}.to_json(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -19,6 +19,8 @@ module W3DHubLauncher
|
|||||||
|
|
||||||
@status = Worker::Request::STATUS_PENDING
|
@status = Worker::Request::STATUS_PENDING
|
||||||
|
|
||||||
|
@verification_data = Worker::Api::VerificationData.new("#{CACHE_PATH}/verification_data-#{@application.id}-#{@channel.id}.json")
|
||||||
|
|
||||||
# caching mechinism for file path normalization
|
# caching mechinism for file path normalization
|
||||||
@file_index = {}
|
@file_index = {}
|
||||||
# manifests!
|
# manifests!
|
||||||
@@ -32,6 +34,10 @@ module W3DHubLauncher
|
|||||||
# packages to verify and/or download
|
# packages to verify and/or download
|
||||||
@packages = []
|
@packages = []
|
||||||
|
|
||||||
|
# whether task should perform a per file checksum or just read it from the cache and
|
||||||
|
# check file modification time and size
|
||||||
|
@force_verification = false
|
||||||
|
|
||||||
setup
|
setup
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -136,7 +142,7 @@ module W3DHubLauncher
|
|||||||
|
|
||||||
# Process manifest game files in NEWEST to OLDEST order so that we don't erroneously flag
|
# Process manifest game files in NEWEST to OLDEST order so that we don't erroneously flag
|
||||||
# valid files as invalid due to an OLDER version of the file being checked FIRST.
|
# valid files as invalid due to an OLDER version of the file being checked FIRST.
|
||||||
@manifest_files.reverse.each do |file|
|
@manifest_files.reverse.each_with_index do |file, i|
|
||||||
break unless File.directory?(@installation_directory)
|
break unless File.directory?(@installation_directory)
|
||||||
|
|
||||||
# skip irrelevant older versions of files
|
# skip irrelevant older versions of files
|
||||||
@@ -147,8 +153,15 @@ module W3DHubLauncher
|
|||||||
next unless File.exist?(file_path) # && !File.directory?(file_path)
|
next unless File.exist?(file_path) # && !File.directory?(file_path)
|
||||||
|
|
||||||
puts "verifying #{file_path}..."
|
puts "verifying #{file_path}..."
|
||||||
checksum = cached_checksums[file_path] || Digest::SHA256.file(file_path).hexdigest.upcase
|
key = @verification_data.key(file.name)
|
||||||
cached_checksums[file_path] ||= checksum
|
pp [key, @force_verification]
|
||||||
|
verification_data = @force_verification ? nil : @verification_data.unchanged?(key, checksum: file.checksum, file_path: file_path)
|
||||||
|
|
||||||
|
# Use cached checksum if the file appears unchanged, otherwise recalculate it
|
||||||
|
checksum = verification_data&.checksum || Digest::SHA256.file(file_path).hexdigest.upcase
|
||||||
|
|
||||||
|
# Set or update cached verification data if files don't match
|
||||||
|
@verification_data.set(key, checksum: checksum, file_path: file_path) unless verification_data
|
||||||
|
|
||||||
if checksum == file.checksum
|
if checksum == file.checksum
|
||||||
@required_manifest_files.delete(file)
|
@required_manifest_files.delete(file)
|
||||||
@@ -159,6 +172,8 @@ module W3DHubLauncher
|
|||||||
else
|
else
|
||||||
puts " failed verification:#{file.version}"
|
puts " failed verification:#{file.version}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
update_status(label: "Verifying files...", fraction: i.to_f / @manifest_files.size)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -249,7 +264,7 @@ module W3DHubLauncher
|
|||||||
if manifest_file.patch?
|
if manifest_file.patch?
|
||||||
apply_patch(manifest_file, package)
|
apply_patch(manifest_file, package)
|
||||||
else
|
else
|
||||||
unzip(package_path)
|
unzip(manifest_file, package_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
processed_packages[package_path] = manifest_file
|
processed_packages[package_path] = manifest_file
|
||||||
@@ -265,6 +280,8 @@ module W3DHubLauncher
|
|||||||
if File.exist?(file_path) && !File.directory?(file_path)
|
if File.exist?(file_path) && !File.directory?(file_path)
|
||||||
puts "Removing file: #{file_path}"
|
puts "Removing file: #{file_path}"
|
||||||
File.delete(file_path)
|
File.delete(file_path)
|
||||||
|
key = @verification_data.key(manifest_file.name)
|
||||||
|
@verification_data.delete(key)
|
||||||
|
|
||||||
remove_from_file_index(file_path)
|
remove_from_file_index(file_path)
|
||||||
end
|
end
|
||||||
@@ -285,7 +302,7 @@ module W3DHubLauncher
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# updated, and moved applications will overwrite existing application data in settings
|
# updated, repaired, and moved applications will overwrite existing application data in settings
|
||||||
def mark_application_installed
|
def mark_application_installed
|
||||||
app = Worker::Api::Settings::Application.create(
|
app = Worker::Api::Settings::Application.create(
|
||||||
id: @application.id,
|
id: @application.id,
|
||||||
@@ -469,7 +486,7 @@ module W3DHubLauncher
|
|||||||
package_path = package_cache_path(package)
|
package_path = package_cache_path(package)
|
||||||
|
|
||||||
puts "unpacking patch..."
|
puts "unpacking patch..."
|
||||||
unzip(package_path, f.path)
|
unzip(false, package_path, output_path: f.path)
|
||||||
|
|
||||||
puts "reading patch data.."
|
puts "reading patch data.."
|
||||||
patch_mix = W3DHubLauncher::WWMix.new(path: f.path)
|
patch_mix = W3DHubLauncher::WWMix.new(path: f.path)
|
||||||
@@ -504,12 +521,16 @@ module W3DHubLauncher
|
|||||||
raise temp_mix.error_reason unless temp_mix.save
|
raise temp_mix.error_reason unless temp_mix.save
|
||||||
|
|
||||||
puts "copying file..."
|
puts "copying file..."
|
||||||
FileUtils.cp(temp.path, normalize_path(manifest_file.name))
|
file_path = normalize_path(manifest_file.name)
|
||||||
|
FileUtils.cp(temp.path, file_path)
|
||||||
|
|
||||||
|
key = @verification_data.key(manifest_file.name)
|
||||||
|
@verification_data.set(key, checksum: manifest_file.checksum, file_path: file_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def unzip(zip_path, output_path = nil)
|
def unzip(manifest_file, zip_path, output_path: nil)
|
||||||
stream = Zip::InputStream.new(File.open(zip_path))
|
stream = Zip::InputStream.new(File.open(zip_path))
|
||||||
|
|
||||||
while(entry = stream.get_next_entry)
|
while(entry = stream.get_next_entry)
|
||||||
@@ -529,6 +550,23 @@ module W3DHubLauncher
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# the manifest file we receive MIGHT NOT be for the current zip file entry
|
||||||
|
# so look it up to be safe
|
||||||
|
if manifest_file
|
||||||
|
manifest = @manifests[manifest_file.version]
|
||||||
|
if manifest
|
||||||
|
entry_manifest_file = manifest.files.find do |f|
|
||||||
|
f.name.gsub("\\", "/").downcase == entry.name.gsub("\\", "/").downcase
|
||||||
|
end
|
||||||
|
|
||||||
|
if entry_manifest_file
|
||||||
|
key = @verification_data.key(entry.name)
|
||||||
|
@verification_data.set(key, checksum: entry_manifest_file.checksum, file_path: file_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
add_to_file_index(file_path)
|
add_to_file_index(file_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ module W3DHubLauncher
|
|||||||
def setup
|
def setup
|
||||||
super
|
super
|
||||||
|
|
||||||
|
# User requested a repair, make sure everything is as it should be!
|
||||||
|
@force_verification = true
|
||||||
|
|
||||||
@task_verb = "Repairing".freeze
|
@task_verb = "Repairing".freeze
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ require_relative "lib/worker/api/server_event"
|
|||||||
require_relative "lib/worker/api/test_event"
|
require_relative "lib/worker/api/test_event"
|
||||||
require_relative "lib/worker/api/legacy_manifest"
|
require_relative "lib/worker/api/legacy_manifest"
|
||||||
require_relative "lib/worker/api/legacy_manifest_package"
|
require_relative "lib/worker/api/legacy_manifest_package"
|
||||||
|
require_relative "lib/worker/api/verification_data"
|
||||||
require_relative "lib/worker/request"
|
require_relative "lib/worker/request"
|
||||||
require_relative "lib/worker/w3dhub_api"
|
require_relative "lib/worker/w3dhub_api"
|
||||||
require_relative "lib/worker/task"
|
require_relative "lib/worker/task"
|
||||||
|
|||||||
Reference in New Issue
Block a user