mirror of
https://github.com/cyberarm/w3d_hub_linux_launcher.git
synced 2026-05-06 09:28:18 +00:00
Compare commits
12 Commits
95187f37f4
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
| 0eb188f72e | |||
| c8bb271d82 | |||
| f1d6bbe390 | |||
| 56bb6a59e2 | |||
| 9d0a99de6e | |||
| e97e5cc862 | |||
| dc9e737587 | |||
| 30776857a2 | |||
| 43f8af42ec | |||
| 33de050cd2 | |||
| 6da57fef70 | |||
| 36610295cd |
18
Gemfile
18
Gemfile
@@ -1,3 +1,21 @@
|
|||||||
source "https://gem.coop"
|
source "https://gem.coop"
|
||||||
|
|
||||||
|
# "standard lib" gems
|
||||||
|
gem "base64"
|
||||||
|
gem "rexml"
|
||||||
|
gem "logger"
|
||||||
|
gem "json"
|
||||||
|
|
||||||
|
# "game" library gem
|
||||||
gem "cyberarm_engine"
|
gem "cyberarm_engine"
|
||||||
|
gem "sdl2-bindings"
|
||||||
|
|
||||||
|
# networking libs
|
||||||
|
gem "async"
|
||||||
|
gem "async-http"
|
||||||
|
gem "async-websocket"
|
||||||
|
|
||||||
|
# misc. libs
|
||||||
|
gem "digest-crc"
|
||||||
|
gem "ircparser"
|
||||||
|
gem "rubyzip"
|
||||||
|
|||||||
111
Gemfile.lock
111
Gemfile.lock
@@ -1,20 +1,125 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://gem.coop/
|
remote: https://gem.coop/
|
||||||
specs:
|
specs:
|
||||||
|
async (2.39.0)
|
||||||
|
console (~> 1.29)
|
||||||
|
fiber-annotation
|
||||||
|
io-event (~> 1.11)
|
||||||
|
metrics (~> 0.12)
|
||||||
|
traces (~> 0.18)
|
||||||
|
async-http (0.95.0)
|
||||||
|
async (>= 2.10.2)
|
||||||
|
async-pool (~> 0.11)
|
||||||
|
io-endpoint (~> 0.14)
|
||||||
|
io-stream (~> 0.6)
|
||||||
|
metrics (~> 0.12)
|
||||||
|
protocol-http (~> 0.62)
|
||||||
|
protocol-http1 (~> 0.39)
|
||||||
|
protocol-http2 (~> 0.26)
|
||||||
|
protocol-url (~> 0.2)
|
||||||
|
traces (~> 0.10)
|
||||||
|
async-pool (0.11.2)
|
||||||
|
async (>= 2.0)
|
||||||
|
async-websocket (0.30.0)
|
||||||
|
async-http (~> 0.76)
|
||||||
|
protocol-http (~> 0.34)
|
||||||
|
protocol-rack (~> 0.7)
|
||||||
|
protocol-websocket (~> 0.17)
|
||||||
|
base64 (0.3.0)
|
||||||
|
console (1.34.3)
|
||||||
|
fiber-annotation
|
||||||
|
fiber-local (~> 1.1)
|
||||||
|
json
|
||||||
cyberarm_engine (0.25.1)
|
cyberarm_engine (0.25.1)
|
||||||
gosu (~> 1.1)
|
gosu (~> 1.1)
|
||||||
|
digest-crc (0.7.0)
|
||||||
|
rake (>= 12.0.0, < 14.0.0)
|
||||||
|
ffi (1.17.4-x86_64-linux-gnu)
|
||||||
|
fiber-annotation (0.2.0)
|
||||||
|
fiber-local (1.1.0)
|
||||||
|
fiber-storage
|
||||||
|
fiber-storage (1.0.1)
|
||||||
gosu (1.4.6)
|
gosu (1.4.6)
|
||||||
|
io-endpoint (0.17.2)
|
||||||
|
io-event (1.15.1)
|
||||||
|
io-stream (0.11.1)
|
||||||
|
ircparser (1.0.0)
|
||||||
|
json (2.19.4)
|
||||||
|
logger (1.7.0)
|
||||||
|
metrics (0.15.0)
|
||||||
|
protocol-hpack (1.5.1)
|
||||||
|
protocol-http (0.62.2)
|
||||||
|
protocol-http1 (0.39.0)
|
||||||
|
protocol-http (~> 0.62)
|
||||||
|
protocol-http2 (0.26.0)
|
||||||
|
protocol-hpack (~> 1.4)
|
||||||
|
protocol-http (~> 0.62)
|
||||||
|
protocol-rack (0.22.1)
|
||||||
|
io-stream (>= 0.10)
|
||||||
|
protocol-http (~> 0.58)
|
||||||
|
rack (>= 1.0)
|
||||||
|
protocol-url (0.4.0)
|
||||||
|
protocol-websocket (0.21.0)
|
||||||
|
protocol-http (~> 0.2)
|
||||||
|
rack (3.2.6)
|
||||||
|
rake (13.4.2)
|
||||||
|
rexml (3.4.4)
|
||||||
|
rubyzip (3.2.2)
|
||||||
|
sdl2-bindings (0.2.3)
|
||||||
|
ffi (~> 1.15)
|
||||||
|
traces (0.18.2)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
|
||||||
x86_64-linux
|
x86_64-linux
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
async
|
||||||
|
async-http
|
||||||
|
async-websocket
|
||||||
|
base64
|
||||||
cyberarm_engine
|
cyberarm_engine
|
||||||
|
digest-crc
|
||||||
|
ircparser
|
||||||
|
json
|
||||||
|
logger
|
||||||
|
rexml
|
||||||
|
rubyzip
|
||||||
|
sdl2-bindings
|
||||||
|
|
||||||
CHECKSUMS
|
CHECKSUMS
|
||||||
cyberarm_engine (0.25.1)
|
async (2.39.0) sha256=df18730073f2bbb45788077dfa20cb365ecc1b9453969f44de6796b5191a00aa
|
||||||
gosu (1.4.6)
|
async-http (0.95.0) sha256=08128cab255a48e41d1e856bfa9cbda001f1c57c88bafa3fa3a545ad795754aa
|
||||||
|
async-pool (0.11.2) sha256=0a43a17b02b04d9c451b7d12fafa9a50e55dc6dd00d4369aca00433f16a7e3ed
|
||||||
|
async-websocket (0.30.0) sha256=55739954528ad8f87f7792d0452e1268d1ef2aa5b3719f79400a05a1a6202cdf
|
||||||
|
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
|
||||||
|
console (1.34.3) sha256=869fbd74697efc4c606f102d2812b0b008e4e7fd738a91c591e8577140ec0dcc
|
||||||
|
cyberarm_engine (0.25.1) sha256=6f851a2ed0a32bdd25fc619172b546a8e26eefeb13a62c509f226337170d0efe
|
||||||
|
digest-crc (0.7.0) sha256=64adc23a26a241044cbe6732477ca1b3c281d79e2240bcff275a37a5a0d78c07
|
||||||
|
ffi (1.17.4-x86_64-linux-gnu) sha256=9d3db14c2eae074b382fa9c083fe95aec6e0a1451da249eab096c34002bc752d
|
||||||
|
fiber-annotation (0.2.0) sha256=7abfadf1d119f508867d4103bf231c0354d019cc39a5738945dec2edadaf6c03
|
||||||
|
fiber-local (1.1.0) sha256=c885f94f210fb9b05737de65d511136ea602e00c5105953748aa0f8793489f06
|
||||||
|
fiber-storage (1.0.1) sha256=f48e5b6d8b0be96dac486332b55cee82240057065dc761c1ea692b2e719240e1
|
||||||
|
gosu (1.4.6) sha256=80c7fa48cf61f4960ef067fdd1c000d98b4adc8e11faeaa486543d00908a5c15
|
||||||
|
io-endpoint (0.17.2) sha256=3feaf766c116b35839c11fac68b6aaadc47887bb488902a57bf8e1d288fb3338
|
||||||
|
io-event (1.15.1) sha256=c644cdcf48254015d63f558bf4492f35471f5bb204a42180ea49752be59b30cc
|
||||||
|
io-stream (0.11.1) sha256=fa5f551fcff99581c1757b9d1cee2c37b124f07d2ca4f40b756a05ab9bd21b87
|
||||||
|
ircparser (1.0.0) sha256=0d4598f691172e2ad078207c50ba62c0d3428ae841836b0a682e6cd01d62878d
|
||||||
|
json (2.19.4) sha256=670a7d333fb3b18ca5b29cb255eb7bef099e40d88c02c80bd42a3f30fe5239ac
|
||||||
|
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
|
||||||
|
metrics (0.15.0) sha256=61ded5bac95118e995b1bc9ed4a5f19bc9814928a312a85b200abbdac9039072
|
||||||
|
protocol-hpack (1.5.1) sha256=6feca238b8078da1cd295677d6f306c6001af92d75fe0643d33e6956cbc3ad91
|
||||||
|
protocol-http (0.62.2) sha256=e1c1f2f56029c1af8c4e2b8a67d0d096c76620f3afd8d99d1dcd2f6b8ffa773b
|
||||||
|
protocol-http1 (0.39.0) sha256=e49b3f4cda6f5d94c76a323d2b7f6977cba3ebd082d2da437039594da77ad8eb
|
||||||
|
protocol-http2 (0.26.0) sha256=bac89cd78082b241ccd0cf7246f5160e4bb0c9c975fb4bf7deef5f88cc317486
|
||||||
|
protocol-rack (0.22.1) sha256=1185d245927ef9849a603700d6991ca353bc89724fbf98efa4a4333ed62a9fc3
|
||||||
|
protocol-url (0.4.0) sha256=64d4c03b6b51ad815ac6fdaf77a1d91e5baf9220d26becb846c5459dacdea9e1
|
||||||
|
protocol-websocket (0.21.0) sha256=6e2ccc2adf7de1895b0f6548fdfacf5f9735c0d4deb56cd2bac1ae38a1952e93
|
||||||
|
rack (3.2.6) sha256=5ed78e1f73b2e25679bec7d45ee2d4483cc4146eb1be0264fc4d94cb5ef212c2
|
||||||
|
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
|
||||||
|
rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
|
||||||
|
rubyzip (3.2.2) sha256=c0ed99385f0625415c8f05bcae33fe649ed2952894a95ff8b08f26ca57ea5b3c
|
||||||
|
sdl2-bindings (0.2.3) sha256=878c0755a4bea1aed0fa85c01596effd1c2b7d1878141ceec5bef808038bd309
|
||||||
|
traces (0.18.2) sha256=80f1649cb4daace1d7174b81f3b3b7427af0b93047759ba349960cb8f315e214
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
4.0.8
|
4.0.8
|
||||||
|
|||||||
14
LICENSE.md
14
LICENSE.md
@@ -1,7 +1,15 @@
|
|||||||
Copyright (c) 2021 cyberarm
|
Copyright (c) 2021-2026 cyberarm
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
|
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||||
|
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
30
lib/attribution.rb
Normal file
30
lib/attribution.rb
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
module Attribution
|
||||||
|
Item = Data.define(:name, :description, :url, :license, :license_url)
|
||||||
|
|
||||||
|
SPECIAL_THANKS = [
|
||||||
|
Item.new("W3D Hub", "Creating awesome games and mods for free", "https://w3dhub.com", "", ""),
|
||||||
|
Item.new("Yukihiro \"matz\" Matsumoto", "Creating the Ruby language", "https://matz.rubyist.net", "", ""),
|
||||||
|
Item.new("Samuel \"ioquatix\" Williams", "Creating and maintaining the async libraries for Ruby", "https://www.codeotaku.com", "", ""),
|
||||||
|
Item.new("Kenney", "Creating awesome game assets and releasing them completely for free\nThe launcher uses their UI Icon pack", "https://kenney.nl", "CC0", "https://creativecommons.org/publicdomain/zero/1.0/"),
|
||||||
|
]
|
||||||
|
|
||||||
|
LIBRARIES = [
|
||||||
|
Item.new("Ruby", "Programming language. A Programmer's Best Friend", "https://ruby-lang.org", "BSD 2-Clause", "https://www.ruby-lang.org/en/about/license.txt"),
|
||||||
|
Item.new("gosu", "Light-weight game library", "https://libgosu.org", "MIT", "https://github.com/gosu/gosu/blob/master/COPYING"),
|
||||||
|
Item.new("SDL2", "Simple DirectMedia Layer", "https://libsdl.org", "MIT", "https://github.com/libsdl-org/SDL/blob/SDL2/LICENSE.txt"),
|
||||||
|
Item.new("MojoAL", "OpenAL sound library implementation in a single C file", "https://icculus.org/mojoAL/", "MIT", "https://github.com/icculus/mojoAL/blob/main/LICENSE.txt"),
|
||||||
|
|
||||||
|
Item.new("async", "Asynchronous event-driven reactor for Ruby", "https://github.com/socketry/async", "MIT", "https://github.com/socketry/async/blob/main/license.md"),
|
||||||
|
Item.new("async-http", "Asynchronous http(s) client/server for Ruby", "https://github.com/socketry/async-http", "MIT", "https://github.com/socketry/async-http/blob/main/license.md"),
|
||||||
|
Item.new("async-websocket", "Asynchronous websockets for Ruby", "https://github.com/socketry/async-websocket", "MIT", "https://github.com/socketry/async-websocket/blob/main/license.md"),
|
||||||
|
Item.new("rubyzip", "Ruby library for reading and writing zip files", "https://github.com/rubyzip/rubyzip", "BSD 2-Clause", "https://github.com/rubyzip/rubyzip/blob/main/LICENSE.md"),
|
||||||
|
Item.new("digest-crc", "Ruby library for reading and writing zip files", "https://github.com/postmodern/digest-crc", "MIT", "https://github.com/postmodern/digest-crc/blob/main/LICENSE.txt"),
|
||||||
|
Item.new("ircparser", "Ruby parser for the IRCv3 message format", "https://codeberg.org/sadiepowell/ircparser-ruby", "MIT", "https://codeberg.org/sadiepowell/ircparser-ruby#license"),
|
||||||
|
|
||||||
|
Item.new("base64", "Ruby library for encoding and decoding base64", "https://github.com/ruby/base64", "BSD 2-Clause", "https://github.com/ruby/base64/blob/master/COPYING"),
|
||||||
|
Item.new("rexml", "Ruby library for parsing XML", "https://github.com/ruby/rexml", "BSD 2-Clause", "https://github.com/ruby/rexml/blob/master/LICENSE.txt"),
|
||||||
|
Item.new("logger", "Ruby logging library", "https://github.com/ruby/logger", "BSD 2-Clause", "https://github.com/ruby/logger/blob/master/COPYING"),
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
11
lib/constants.rb
Normal file
11
lib/constants.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
DIRECTORY_NAME = "w3d-hub-linux-launcher".freeze
|
||||||
|
|
||||||
|
ROOT_PATH = Dir.pwd
|
||||||
|
CONFIG_PATH = "#{Dir.home}/.config/#{DIRECTORY_NAME}".freeze
|
||||||
|
CACHE_PATH = "#{Dir.home}/.cache/#{DIRECTORY_NAME}".freeze
|
||||||
|
DEFAULT_PACKAGE_CACHE_PATH = "#{CACHE_PATH}/packages".freeze
|
||||||
|
DEFAULT_APPLICATIONS_PATH = "#{Dir.home}/.local/share/#{DIRECTORY_NAME}/applications".freeze
|
||||||
|
|
||||||
|
USER_AGENT = "#{NAME} v#{VERSION}".freeze
|
||||||
|
end
|
||||||
9
lib/dialog.rb
Normal file
9
lib/dialog.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class Dialog < CyberarmEngine::Dialog
|
||||||
|
def setup
|
||||||
|
theme(THEME)
|
||||||
|
|
||||||
|
background 0xee_222222
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,12 +1,51 @@
|
|||||||
module W3DHubLauncher
|
module W3DHubLauncher
|
||||||
module Dialogs
|
class Dialog
|
||||||
class About < CyberarmEngine::GuiState # Dialog
|
class About < W3DHubLauncher::Dialog
|
||||||
def setup
|
def setup
|
||||||
# application name and version
|
super
|
||||||
# authorship
|
|
||||||
# special thanks
|
stack(width: 1.0, max_width: 600, height: 1.0, max_height: 600, h_align: :center, v_align: :center, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_BLACK) do
|
||||||
# used gems and libraries
|
flow(width: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) do
|
||||||
# useful links
|
banner "About", width: 1.0, text_align: :center
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(width: 1.0, fill: true, scroll: true, padding_left: PADDING, padding_right: PADDING) do
|
||||||
|
title NAME
|
||||||
|
tagline format("v%s (%s)", VERSION, VERSION_NAME), margin_left: PADDING
|
||||||
|
para "© 2021 - #{Time.now.year} cyberarm", margin_left: PADDING
|
||||||
|
link "MIT licence", margin_left: PADDING
|
||||||
|
|
||||||
|
title "Special Thanks", margin_top: LARGE_PADDING
|
||||||
|
W3DHubLauncher::Attribution::SPECIAL_THANKS.each do |item|
|
||||||
|
present_item(item)
|
||||||
|
end
|
||||||
|
|
||||||
|
title "Software / Libraries", margin_top: LARGE_PADDING
|
||||||
|
W3DHubLauncher::Attribution::LIBRARIES.each do |item|
|
||||||
|
present_item(item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(width: 1.0, padding: PADDING, background_nine_slice: NINE_SLICE_ROUNDED_BOTTOM, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) do
|
||||||
|
flow(fill: true)
|
||||||
|
|
||||||
|
button "Close" do
|
||||||
|
pop_state
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(fill: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def present_item(item)
|
||||||
|
unless item.url.empty?
|
||||||
|
link item.name, tip: item.url, margin_left: PADDING, font: FONT_BOLD
|
||||||
|
else
|
||||||
|
tagline item.name, margin_left: PADDING
|
||||||
|
end
|
||||||
|
para item.description, margin_left: LARGE_PADDING
|
||||||
|
link item.license, tip: item.license_url, margin_left: PADDING + LARGE_PADDING unless item.license.empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
38
lib/dialogs/downloads.rb
Normal file
38
lib/dialogs/downloads.rb
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class Dialog
|
||||||
|
class Downloads < W3DHubLauncher::Dialog
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
|
stack(width: 1.0, max_width: 600, height: 1.0, max_height: 600, h_align: :center, v_align: :center, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_BLACK) do
|
||||||
|
flow(width: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) do
|
||||||
|
banner "Downloads", width: 1.0, text_align: :center
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(width: 1.0, fill: true, scroll: true, padding_left: PADDING, padding_right: PADDING) do
|
||||||
|
50.times do
|
||||||
|
stack(width: 1.0, margin_top: HALF_PADDING, margin_bottom: HALF_PADDING) do
|
||||||
|
flow(width: 1.0) do
|
||||||
|
para "PACKAGE_NAME.mix"
|
||||||
|
flow(fill: true)
|
||||||
|
para ["Downloading...", "Pending...", "Done.", "Patching...", "Unpacking..."].sample
|
||||||
|
end
|
||||||
|
progress(width: 1.0, fraction: rand)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(width: 1.0, padding: PADDING, background_nine_slice: NINE_SLICE_ROUNDED_BOTTOM, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) do
|
||||||
|
flow(fill: true)
|
||||||
|
|
||||||
|
button "Close" do
|
||||||
|
pop_state
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(fill: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -6,14 +6,14 @@ module W3DHubLauncher
|
|||||||
def safe_get_image(path, retro: false)
|
def safe_get_image(path, retro: false)
|
||||||
return get_image(path, retro: retro) if File.exist?(path)
|
return get_image(path, retro: retro) if File.exist?(path)
|
||||||
|
|
||||||
path = "./media/default.png"
|
path = "#{ROOT_PATH}/media/default.png"
|
||||||
return get_image(path, retro: retro) if File.exist?(path)
|
return get_image(path, retro: retro) if File.exist?(path)
|
||||||
|
|
||||||
WHITE_IMAGE
|
WHITE_IMAGE
|
||||||
end
|
end
|
||||||
|
|
||||||
def rounded_avatar(image)
|
def rounded_avatar(image)
|
||||||
circle = get_image("./media/ui/circle.png")
|
circle = get_image("#{ROOT_PATH}/media/ui/circle.png")
|
||||||
scale = [(circle.width.to_f / image.width).abs, (circle.width.to_f / image.height).abs].min
|
scale = [(circle.width.to_f / image.width).abs, (circle.width.to_f / image.height).abs].min
|
||||||
|
|
||||||
Gosu.render(circle.width, circle.height) do
|
Gosu.render(circle.width, circle.height) do
|
||||||
|
|||||||
68
lib/pages/boot/initial_setup.rb
Normal file
68
lib/pages/boot/initial_setup.rb
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
module Page
|
||||||
|
module Boot
|
||||||
|
class InitialSetup < CyberarmEngine::Page
|
||||||
|
include GuiExt
|
||||||
|
|
||||||
|
def setup
|
||||||
|
stack(width: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: 8, background_nine_slice_color: 0x11_ffffff, padding: HALF_PADDING) do
|
||||||
|
banner "Welcome to #{NAME}", width: 1.0, text_align: :center
|
||||||
|
tagline "Your gateway to the world of W3D Hub games.", width: 1.0, text_align: :center
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(width: 1.0, fill: true, padding: PADDING) do
|
||||||
|
stack(width: 1.0, fill: true, scroll: true) do
|
||||||
|
title "Initial Setup"
|
||||||
|
caption "Please confirm launcher's default settings and make any desired tweaks.", font: FONT_REGULAR
|
||||||
|
|
||||||
|
flow(width: 1.0, height: 40, margin_top: HALF_PADDING) do
|
||||||
|
tagline "Launcher package cache directory", height: 1.0, text_v_align: :center
|
||||||
|
edit_line DEFAULT_PACKAGE_CACHE_PATH, fill: true
|
||||||
|
button "Browse..."
|
||||||
|
end
|
||||||
|
inscription "Location where the launcher will download application packages."
|
||||||
|
|
||||||
|
flow(width: 1.0, height: 40, margin_top: HALF_PADDING) do
|
||||||
|
tagline "Application installation directory", height: 1.0, text_v_align: :center
|
||||||
|
edit_line DEFAULT_APPLICATIONS_PATH, fill: true
|
||||||
|
button "Browse..."
|
||||||
|
end
|
||||||
|
inscription "Location where the launcher will install new applications."
|
||||||
|
|
||||||
|
flow(width: 1.0, height: 40, margin_top: HALF_PADDING) do
|
||||||
|
tagline "Wine context", height: 1.0, text_v_align: :center
|
||||||
|
edit_line "", fill: true
|
||||||
|
button "Browse..."
|
||||||
|
end
|
||||||
|
inscription "Location of wine context to use. Leave blank to use default."
|
||||||
|
|
||||||
|
flow(width: 1.0, height: 40, margin_top: HALF_PADDING) do
|
||||||
|
tagline "Wine command", height: 1.0, text_v_align: :center
|
||||||
|
edit_line "wine", fill: true
|
||||||
|
button "Browse..."
|
||||||
|
end
|
||||||
|
inscription "Path to wine executable. Use `wine` for system installed wine."
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(width: 1.0, padding_top: PADDING) do
|
||||||
|
flow(fill: true)
|
||||||
|
button "Accept" do |btn|
|
||||||
|
btn.enabled = false
|
||||||
|
|
||||||
|
Worker::Api.update_settings({}) do |result|
|
||||||
|
if result.okay?
|
||||||
|
page(Page::Boot::StartUp)
|
||||||
|
else
|
||||||
|
btn.enabled = true
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "NOW!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
82
lib/pages/boot/start_up.rb
Normal file
82
lib/pages/boot/start_up.rb
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
module Page
|
||||||
|
module Boot
|
||||||
|
class StartUp < CyberarmEngine::Page
|
||||||
|
include GuiExt
|
||||||
|
|
||||||
|
def setup
|
||||||
|
stack(width: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: 8, background_nine_slice_color: 0x11_ffffff, padding: HALF_PADDING) do
|
||||||
|
banner "Establishing Battlefield Control", width: 1.0, text_align: :center
|
||||||
|
tagline "Please stand by...", width: 1.0, text_align: :center
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(width: 1.0, fill: true, padding: PADDING) do
|
||||||
|
stack(width: 1.0, fill: true, scroll: true) do
|
||||||
|
a = flow(width: 1.0, height: HALF_PADDING + PADDING, visible: false) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/checkmark.png"), height: 1.0, v_align: :center
|
||||||
|
tagline "DNS resolution", height: 1.0, text_v_align: :center
|
||||||
|
end
|
||||||
|
after(500) do
|
||||||
|
a.show
|
||||||
|
end
|
||||||
|
b = flow(width: 1.0, height: HALF_PADDING + PADDING, visible: false) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/information.png"), height: 1.0, v_align: :center, color: 0xff_ff8800
|
||||||
|
tagline "Upstream backend", height: 1.0, text_v_align: :center
|
||||||
|
caption "Notice: Unreachable. Accounts will be unavailable.", height: 1.0, text_v_align: :center, color: 0xff_ff8800
|
||||||
|
end
|
||||||
|
after(1000) do
|
||||||
|
b.show
|
||||||
|
end
|
||||||
|
c = flow(width: 1.0, height: HALF_PADDING + PADDING, visible: false) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/checkmark.png"), height: 1.0, v_align: :center
|
||||||
|
tagline "Alternate backend", height: 1.0, text_v_align: :center
|
||||||
|
end
|
||||||
|
after(1500) do
|
||||||
|
c.show
|
||||||
|
end
|
||||||
|
d = flow(width: 1.0, height: HALF_PADDING + PADDING, visible: false) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/information.png"), height: 1.0, v_align: :center, color: 0xff_ff8800
|
||||||
|
tagline "Refresh account session", height: 1.0, text_v_align: :center
|
||||||
|
caption "Notice: Upstream backend unavailable, session not refreshed.", height: 1.0, text_v_align: :center, color: 0xff_ff8800
|
||||||
|
end
|
||||||
|
after(2000) do
|
||||||
|
d.show
|
||||||
|
end
|
||||||
|
e = flow(width: 1.0, height: HALF_PADDING + PADDING, visible: false) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/checkmark.png"), height: 1.0, v_align: :center
|
||||||
|
tagline "Fetch game servers", height: 1.0, text_v_align: :center
|
||||||
|
end
|
||||||
|
after(2500) do
|
||||||
|
e.show
|
||||||
|
end
|
||||||
|
f = flow(width: 1.0, height: HALF_PADDING + PADDING, visible: false) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/cross.png"), height: 1.0, v_align: :center, color: 0xff_ff0000
|
||||||
|
tagline "Fetch applications", height: 1.0, text_v_align: :center
|
||||||
|
caption "Fatal: Failed to retrieve applications list and no local cache exists. Cannot continue.", height: 1.0, text_v_align: :center, color: 0xff_ff0000
|
||||||
|
end
|
||||||
|
after(3000) do
|
||||||
|
f.show
|
||||||
|
@progress_bar.type = :linear
|
||||||
|
@progress_bar.value = 0.0
|
||||||
|
end
|
||||||
|
|
||||||
|
after(3500) do
|
||||||
|
parent.page_host.clear do
|
||||||
|
banner "Battlefield control established".upcase, width: 1.0, height: 1.0, text_v_align: :center, text_align: :center
|
||||||
|
end
|
||||||
|
end
|
||||||
|
after(3600) do
|
||||||
|
pop_state
|
||||||
|
push_state(States::Interface)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(width: 1.0, padding_top: PADDING) do
|
||||||
|
@progress_bar = progress width: 1.0, type: :marquee
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
38
lib/pages/boot/terms.rb
Normal file
38
lib/pages/boot/terms.rb
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
module Page
|
||||||
|
module Boot
|
||||||
|
class Terms < CyberarmEngine::Page
|
||||||
|
include GuiExt
|
||||||
|
|
||||||
|
TERMS_AND_CONDITIONS = <<~TERMS
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
TERMS
|
||||||
|
|
||||||
|
def setup
|
||||||
|
flow(width: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: 8, background_nine_slice_color: 0x11_ffffff, padding: HALF_PADDING) do
|
||||||
|
banner "Terms and Conditions", width: 1.0, text_align: :center
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(width: 1.0, fill: true, padding: PADDING) do
|
||||||
|
stack(width: 1.0, fill: true, scroll: true, padding_bottom: PADDING) do
|
||||||
|
tagline TERMS_AND_CONDITIONS, font: FONT_REGULAR
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(width: 1.0) do
|
||||||
|
flow(fill: true)
|
||||||
|
button "Decline", margin_right: PADDING do
|
||||||
|
window.close
|
||||||
|
end
|
||||||
|
|
||||||
|
button "Accept" do
|
||||||
|
page(Page::Boot::InitialSetup)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
module Page
|
||||||
|
class Games < CyberarmEngine::Page
|
||||||
|
include GuiExt
|
||||||
|
|
||||||
|
def setup
|
||||||
|
# game bar container
|
||||||
|
flow(width: 1.0, height: 60) do
|
||||||
|
widget(width: 220, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY, hover: { background_nine_slice_color: ALPHA_BLACK }, active: { background_nine_slice_color: ALPHA_GRAY }) do
|
||||||
|
flow(width: 1.0, height: 40, margin_left: PADDING, v_align: :center, h_align: :center) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/menuGrid.png"), height: 40, color: 0xff_bbbbbb
|
||||||
|
link "ALL GAMES", text_size: 24, font: FONT_BLACK, height: 1.0, text_v_align: :center
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY, margin_left: PADDING) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/apb.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0x88_5e5c64, border_thickness_bottom: 3, border_color_bottom: 0xff_3584e4, tip: "Red Alert: A Path Beyond"
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/ren.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Command & Conquer: Renegade"
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/tsr.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Tiberian Sun: Reborn"
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/woa.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Battle for Dune: War of Assassins"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# game content container
|
||||||
|
flow(width: 1.0, fill: true, margin_top: LARGE_PADDING) do
|
||||||
|
# game info container
|
||||||
|
stack(width: 340, height: 1.0) do
|
||||||
|
# logo
|
||||||
|
image safe_get_image("/run/media/cyberarm/Storage/W3DHub/Launcher/package-cache/games/apb/logo.png.package"), width: 1.0, max_height: 124
|
||||||
|
|
||||||
|
# web links
|
||||||
|
stack(width: 1.0, fill: true, padding: 0, padding_top: LARGE_PADDING) do
|
||||||
|
link "Modifications", text_size: 24
|
||||||
|
link "Bug Tracker", text_size: 24
|
||||||
|
link "Player Statistics", text_size: 24
|
||||||
|
end
|
||||||
|
|
||||||
|
# launching ta game
|
||||||
|
caption "Game Version"
|
||||||
|
list_box items: [ "Release", "Open Testing" ], width: 1.0, margin_bottom: PADDING
|
||||||
|
flow(width: 1.0, height: 60) do
|
||||||
|
button "PLAY", fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_LEFT, **CTA_BUTTON_THEME
|
||||||
|
button safe_get_image("#{ROOT_PATH}/media/icons/singleplayer.png"), image_height: 1.0, background_nine_slice: NINE_SLICE_SQUARE, **CTA_BUTTON_THEME
|
||||||
|
button safe_get_image("#{ROOT_PATH}/media/icons/gear.png"), image_height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_RIGHT, **CTA_BUTTON_THEME
|
||||||
|
end
|
||||||
|
inscription "Version: 3.9.2.15", margin_top: PADDING
|
||||||
|
end
|
||||||
|
|
||||||
|
# game events and news container
|
||||||
|
stack(fill: true, height: 1.0, margin_left: LARGE_PADDING, scroll: true) do
|
||||||
|
flow(width: 1.0, height: 1.0, max_height: 380, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/background.png"), fill: true, aspect_ratio: 16.0 / 9.0
|
||||||
|
|
||||||
|
stack(fill: true, height: 1.0, margin_left: PADDING) do
|
||||||
|
caption "Upcoming Event".upcase, color: 0xff_22aa11
|
||||||
|
title "Red Alert: A Path Beyond Game Night"
|
||||||
|
tagline "July 11, 2028"
|
||||||
|
|
||||||
|
flow(fill: true)
|
||||||
|
|
||||||
|
button "Read More", margin_left: PADDING, margin_right: LARGE_PADDING, margin_bottom: PADDING, width: 1.0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# news container
|
||||||
|
flow(width: 1.0, margin_top: PADDING) do
|
||||||
|
9.times do
|
||||||
|
stack(width: 1.0 / 3, min_width: 345, height: 345, aspect_ratio: 1, margin_left: HALF_PADDING, margin_right: HALF_PADDING, margin_bottom: PADDING) do
|
||||||
|
stack(width: 1.0, fill: true, background_image: safe_get_image("#{ROOT_PATH}/media/background.png"), background_image_mode: :fill)
|
||||||
|
stack(width: 1.0, height: 1.0 / 3, padding: PADDING, v_align: :bottom, background_nine_slice: NINE_SLICE_ROUNDED_BOTTOM, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY, border_thickness_top: 1, border_color_top: Gosu::Color::BLACK) do
|
||||||
|
caption "NEWS", color: 0x88_ffffff
|
||||||
|
tagline "A News Item Post A News Item Post"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
module Page
|
||||||
|
class ServerBrowser < CyberarmEngine::Page
|
||||||
|
include GuiExt
|
||||||
|
|
||||||
|
def setup
|
||||||
|
# game bar container
|
||||||
|
flow(width: 1.0, height: 60) do
|
||||||
|
flow(width: 220, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) do
|
||||||
|
flow(width: 1.0, height: 40, margin_left: PADDING, v_align: :center, h_align: :center) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/menuGrid.png"), height: 40, color: 0xff_bbbbbb
|
||||||
|
link "ALL SERVERS", text_size: 24, font: FONT_BLACK, height: 1.0, text_v_align: :center
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
flow(fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY, margin_left: PADDING) do
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/apb.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0x88_5e5c64, border_thickness_bottom: 3, border_color_bottom: 0xff_3584e4, tip: "Red Alert: A Path Beyond"
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/ren.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Command & Conquer: Renegade"
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/tsr.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Tiberian Sun: Reborn"
|
||||||
|
image safe_get_image("#{ROOT_PATH}/data/cache/woa.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Battle for Dune: War of Assassins"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# game content container
|
||||||
|
stack(width: 1.0, fill: true, margin_top: LARGE_PADDING, scroll: true) do
|
||||||
|
10.times do
|
||||||
|
widget(width: 1.0, height: 48, padding_top: HALF_PADDING, padding_bottom: HALF_PADDING, margin_bottom: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY, hover: { background_nine_slice_color: 0xff_5e5c64 } , active: { background_nine_slice_color: 0xaa_5e5c64 }) do
|
||||||
|
# app icon container
|
||||||
|
image(safe_get_image("#{ROOT_PATH}/data/cache/apb.png"), tip: "Red Alert: A Path Beyond", width: 48, height: 1.0, margin_left: HALF_PADDING)
|
||||||
|
# friend name and status container
|
||||||
|
stack(fill: true, height: 1.0, margin_left: HALF_PADDING) do
|
||||||
|
stack(v_align: :center) do
|
||||||
|
# server name
|
||||||
|
server_name = ["Really Long Server Name Goes Here", "[US][W3D Hub] APB Game Night", "[US][W3D Hub] APB Co-op 3.7", "Really Long Server Name Goes Here Really Long Server Name Goes Here"].sample
|
||||||
|
caption server_name, text_wrap: :none, tip: server_name
|
||||||
|
# server info
|
||||||
|
a = ["North America", "South America", "Europe", "Asia", "Antarctica", "Arctica", "Oceania"]
|
||||||
|
inscription "#{a.sample} • 13:52 / #{rand > 0.5 ? '∞' : '30:00'}", text_wrap: :none, margin_top: -HALF_PADDING
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# server map
|
||||||
|
stack(width: 256, height: 1.0, margin_left: HALF_PADDING) do
|
||||||
|
stack(width: 1.0, fill: true, v_align: :center) do
|
||||||
|
server_map = ["RA_Under", "C&C Superduple Long Map Name Goes Here", "RA_NorthByNorthWest", "RA_HostileWatersParadox", "RA_PacificThreat"].sample
|
||||||
|
caption server_map, tip: server_map, text_wrap: :none, width: 1.0, text_align: :center
|
||||||
|
inscription "map", text_wrap: :none, width: 1.0, text_align: :center, margin_top: -HALF_PADDING
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# server player count
|
||||||
|
stack(width: 96, height: 1.0, margin_left: HALF_PADDING) do
|
||||||
|
stack(width: 1.0, fill: true, v_align: :center) do
|
||||||
|
caption format("%d / %d", rand(60), rand(60..127)), width: 1.0, text_align: :center
|
||||||
|
inscription "players", text_wrap: :none, width: 1.0, text_align: :center, margin_top: -HALF_PADDING
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# server ping
|
||||||
|
flow(width: 96, height: 1.0, margin_left: HALF_PADDING, margin_right: HALF_PADDING) do
|
||||||
|
stack(fill: true, height: 1.0, v_align: :center) do
|
||||||
|
caption rand > 0.85 ? "?" : format("%d ms", rand(16..360)), width: 1.0, text_align: :center
|
||||||
|
inscription "ping", text_wrap: :none, width: 1.0, text_align: :center, margin_top: -HALF_PADDING
|
||||||
|
end
|
||||||
|
stack(width: 8, height: rand(0.25..1.0), v_align: :center, min_height: 8, background_nine_slice: NINE_SLICE_ROUNDED_SMALL, background_nine_slice_from_edge: NINE_SLICE_EDGE_SMALL, background_nine_slice_color: [0xff_26a269, 0xff_e5a50a, 0xff_a51d2d, 0xff_3d3846].sample)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
9
lib/state.rb
Normal file
9
lib/state.rb
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class State < CyberarmEngine::GuiState
|
||||||
|
include W3DHubLauncher::GuiExt
|
||||||
|
|
||||||
|
def setup
|
||||||
|
theme(THEME)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class States
|
||||||
|
class Boot < W3DHubLauncher::State
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
|
# root container - background image
|
||||||
|
stack(width: 1.0, height: 1.0, background_image: safe_get_image("/run/media/cyberarm/Storage/W3DHub/Launcher/package-cache/games/apb/background.png.package"), background_image_mode: :fill) do
|
||||||
|
# root container - background image tint
|
||||||
|
flow(width: 1.0, height: 1.0, background: 0xaa_000000) do
|
||||||
|
# content container
|
||||||
|
stack(fill: true, height: 1.0, margin: PADDING, margin_right: PADDING) do
|
||||||
|
# header bar container
|
||||||
|
flow(width: 1.0, height: 80, margin_bottom: PADDING) do |c|
|
||||||
|
# logo image
|
||||||
|
image(safe_get_image("#{ROOT_PATH}/media/logo.png"), height: 1.0)
|
||||||
|
|
||||||
|
stack(fill: true, height: 1.0) do
|
||||||
|
stack(fill: true)
|
||||||
|
title NAME
|
||||||
|
stack(fill: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@page_host = stack(width: 1.0, fill: true, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: 8, background_nine_slice_color: ALPHA_GRAY) do
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
page(Page::Boot::Terms)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -0,0 +1,139 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class States
|
||||||
|
class Interface < W3DHubLauncher::State
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
|
# root container - background image
|
||||||
|
stack(width: 1.0, height: 1.0, background_image: safe_get_image("/run/media/cyberarm/Storage/W3DHub/Launcher/package-cache/games/apb/background.png.package"), background_image_mode: :fill) do
|
||||||
|
# root container - background image tint
|
||||||
|
stack(width: 1.0, height: 1.0, background: ALPHA_BLACK) do
|
||||||
|
# content container
|
||||||
|
stack(width: 1.0, fill: true, margin: PADDING) do
|
||||||
|
# header bar container
|
||||||
|
flow(width: 1.0, height: 80, margin_bottom: PADDING) do |c|
|
||||||
|
# logo + menu button
|
||||||
|
button(safe_get_image("#{ROOT_PATH}/media/logo.png"), image_height: 1.0, background: 0, border_color: 0, hover: { background: 0 }, active: { background: 0, color: 0xff_ffffff }) do |btn|
|
||||||
|
menu(parent: btn) do
|
||||||
|
menu_item("Settings")
|
||||||
|
menu_item("About") do
|
||||||
|
dialog(Dialog::About)
|
||||||
|
end
|
||||||
|
menu_item("Exit") do
|
||||||
|
window.close
|
||||||
|
end
|
||||||
|
end.show
|
||||||
|
end
|
||||||
|
|
||||||
|
# navigation bar container
|
||||||
|
stack(fill: true, height: 1.0) do
|
||||||
|
# stack(fill: true)
|
||||||
|
|
||||||
|
# navigation container
|
||||||
|
flow(width: 1.0) do
|
||||||
|
link("GAMES", text_v_align: :center, font: FONT_BLACK, margin_left: PADDING) { page(Page::Games) }
|
||||||
|
link("SERVERS", text_v_align: :center, font: FONT_BLACK, margin_left: PADDING) { page(Page::ServerBrowser) }
|
||||||
|
stack(fill: true)
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/import.png"), height: 40, color: 0xff_bbbbbb, tip: "Downloads" do |img|
|
||||||
|
dialog(Dialog::Downloads)
|
||||||
|
end
|
||||||
|
image safe_get_image("#{ROOT_PATH}/media/icons/information.png"), height: 40, color: 0xff_bbbbbb, tip: "Notifications"
|
||||||
|
end
|
||||||
|
# application task status bar container
|
||||||
|
stack(width: 1.0, fill: true, margin_left: PADDING) do
|
||||||
|
flow(width: 1.0) do
|
||||||
|
para "Updating Red Alert: A Path Beyond (Release)"
|
||||||
|
stack(fill: true)
|
||||||
|
para "Fetching manifests..."
|
||||||
|
end
|
||||||
|
progress(width: 1.0, fraction: 0.75)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# self account container
|
||||||
|
flow(width: 300, height: 80, margin_left: LARGE_PADDING) do
|
||||||
|
# self avatar container
|
||||||
|
stack(width: 80, height: 1.0, background_image: rounded_avatar(safe_get_image("#{ROOT_PATH}/media/default.png"))) do
|
||||||
|
# self online state container
|
||||||
|
stack(width: 20, height: 20, v_align: :bottom, h_align: :right, background_image: safe_get_image("#{ROOT_PATH}/media/ui/circle_small.png"), background_image_color: 0xff_26a269)
|
||||||
|
end
|
||||||
|
|
||||||
|
stack(fill: true, height: 1.0, margin_left: HALF_PADDING) do
|
||||||
|
flow(fill: true)
|
||||||
|
# self name
|
||||||
|
caption "cyberarm", font: FONT_BLACK, text_wrap: :none
|
||||||
|
# self set online state
|
||||||
|
link "Online ▼", text_size: 18 do |l|
|
||||||
|
menu(parent: l) do
|
||||||
|
menu_item("Online")
|
||||||
|
menu_item("Do Not Disturb")
|
||||||
|
menu_item("Away")
|
||||||
|
menu_item("Invisible")
|
||||||
|
menu_item("Sign Out")
|
||||||
|
end.show
|
||||||
|
end
|
||||||
|
flow(fill: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# layout container
|
||||||
|
flow(width: 1.0, fill: true) do
|
||||||
|
# page host container
|
||||||
|
@page_host = stack(fill: true, height: 1.0) do
|
||||||
|
end
|
||||||
|
|
||||||
|
# battleview/friends container
|
||||||
|
@battleview_container = stack(width: 300, height: 1.0, margin_left: LARGE_PADDING, visible: true) do
|
||||||
|
# friend management container
|
||||||
|
flow(width: 1.0, height: 60) do
|
||||||
|
flow(width: 1.0, v_align: :center) do
|
||||||
|
button safe_get_image("#{ROOT_PATH}/media/icons/singleplayer.png"), image_height: 1.0
|
||||||
|
button safe_get_image("#{ROOT_PATH}/media/icons/gear.png"), image_height: 1.0, margin_left: HALF_PADDING
|
||||||
|
edit_line "", margin_left: HALF_PADDING, fill: true, height: 1.0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# friends/clanmates list container
|
||||||
|
stack(width: 1.0, fill: true, margin_top: LARGE_PADDING, scroll: true) do
|
||||||
|
50.times do |i|
|
||||||
|
# friend container
|
||||||
|
widget(width: 1.0, height: 48, padding_top: HALF_PADDING, padding_bottom: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, hover: { background_nine_slice_color: ALPHA_GRAY }, active: { background_nine_slice_color: ALPHA_BLACK }) do |w|
|
||||||
|
w.subscribe(:clicked_left_mouse_button) do
|
||||||
|
puts "HELLO THERE"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# friend avatar container
|
||||||
|
stack(width: 48, height: 1.0, margin_left: HALF_PADDING, background_image: rounded_avatar(safe_get_image("#{ROOT_PATH}/media/default.png"))) do
|
||||||
|
stack(width: 12, height: 12, v_align: :bottom, h_align: :right, background_image: safe_get_image("#{ROOT_PATH}/media/ui/circle_small.png"), background_image_color: 0xff_26a269)
|
||||||
|
end
|
||||||
|
# friend name and status container
|
||||||
|
stack(fill: true, height: 1.0, margin_left: HALF_PADDING, margin_right: HALF_PADDING) do
|
||||||
|
stack(v_align: :center) do
|
||||||
|
caption ["Silverlight", "PXD2000", "Alstar", "SteelGhost", "FRAYDO"].sample, text_wrap: :none
|
||||||
|
inscription "RA_Under • 13:52", text_wrap: :none, margin_top: -HALF_PADDING
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# friend active application container
|
||||||
|
stack(width: 48, height: 1.0, margin_right: HALF_PADDING, background_image: safe_get_image("#{ROOT_PATH}/media/logo.png"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
page(Page::Games)
|
||||||
|
end
|
||||||
|
|
||||||
|
def button_up(id)
|
||||||
|
super
|
||||||
|
|
||||||
|
@battleview_container.toggle if id == Gosu::KB_F8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
70
lib/theme.rb
70
lib/theme.rb
@@ -3,24 +3,38 @@ module W3DHubLauncher
|
|||||||
PADDING = 20
|
PADDING = 20
|
||||||
HALF_PADDING = 10
|
HALF_PADDING = 10
|
||||||
ALPHA_BLACK = 0x88_000000
|
ALPHA_BLACK = 0x88_000000
|
||||||
|
ALPHA_GRAY = 0x88_5e5c64
|
||||||
|
|
||||||
FONT_LIGHT = "./media/fonts/NotoSans-Light.ttf"
|
FONT_LIGHT = "#{ROOT_PATH}/media/fonts/NotoSans-Light.ttf"
|
||||||
FONT_REGULAR = "./media/fonts/NotoSans-Regular.ttf"
|
FONT_REGULAR = "#{ROOT_PATH}/media/fonts/NotoSans-Regular.ttf"
|
||||||
FONT_BOLD = "./media/fonts/NotoSans-Bold.ttf"
|
FONT_BOLD = "#{ROOT_PATH}/media/fonts/NotoSans-Bold.ttf"
|
||||||
FONT_BLACK = "./media/fonts/NotoSans-Black.ttf"
|
FONT_BLACK = "#{ROOT_PATH}/media/fonts/NotoSans-Black.ttf"
|
||||||
|
|
||||||
FONT_MONO = "./media/fonts/NotoSansMono-Regular.ttf"
|
FONT_MONO = "#{ROOT_PATH}/media/fonts/NotoSansMono-Regular.ttf"
|
||||||
|
|
||||||
NINE_SLICE_EDGE = 8
|
NINE_SLICE_EDGE = 8
|
||||||
NINE_SLICE_ROUNDED = "./media/ui/rounded.png"
|
NINE_SLICE_EDGE_SMALL = 4
|
||||||
NINE_SLICE_ROUNDED_LEFT = "./media/ui/rounded_left.png"
|
NINE_SLICE_EDGE_TINY = 2
|
||||||
NINE_SLICE_ROUNDED_RIGHT = "./media/ui/rounded_right.png"
|
NINE_SLICE_ROUNDED = "#{ROOT_PATH}/media/ui/rounded.png"
|
||||||
NINE_SLICE_ROUNDED_TOP = "./media/ui/rounded_top.png"
|
NINE_SLICE_ROUNDED_SMALL = "#{ROOT_PATH}/media/ui/rounded_small.png"
|
||||||
NINE_SLICE_ROUNDED_BOTTOM = "./media/ui/rounded_bottom.png"
|
NINE_SLICE_ROUNDED_TINY = "#{ROOT_PATH}/media/ui/rounded_small.png"
|
||||||
NINE_SLICE_SQUARE = "./media/ui/square.png"
|
NINE_SLICE_ROUNDED_LEFT = "#{ROOT_PATH}/media/ui/rounded_left.png"
|
||||||
|
NINE_SLICE_ROUNDED_RIGHT = "#{ROOT_PATH}/media/ui/rounded_right.png"
|
||||||
|
NINE_SLICE_ROUNDED_TOP = "#{ROOT_PATH}/media/ui/rounded_top.png"
|
||||||
|
NINE_SLICE_ROUNDED_BOTTOM = "#{ROOT_PATH}/media/ui/rounded_bottom.png"
|
||||||
|
NINE_SLICE_SQUARE = "#{ROOT_PATH}/media/ui/square.png"
|
||||||
|
|
||||||
CTA_BUTTON_THEME = {
|
CTA_BUTTON_THEME = {
|
||||||
background_nine_slice_color: 0xff_1a5fb4
|
color: 0xff_ffffff,
|
||||||
|
background_nine_slice_color: 0xff_1c71d8,
|
||||||
|
hover: {
|
||||||
|
color: 0xff_ffffff,
|
||||||
|
background_nine_slice_color: 0xff_3584e4
|
||||||
|
},
|
||||||
|
active: {
|
||||||
|
color: 0xff_ffffff,
|
||||||
|
background_nine_slice_color: 0xff_1a5fb4
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
THEME = {
|
THEME = {
|
||||||
@@ -40,6 +54,24 @@ module W3DHubLauncher
|
|||||||
color: 0xff_888888
|
color: 0xff_888888
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Inscription: {
|
||||||
|
text_size: 18
|
||||||
|
},
|
||||||
|
Para: {
|
||||||
|
text_size: 20
|
||||||
|
},
|
||||||
|
Caption: {
|
||||||
|
font: FONT_BOLD
|
||||||
|
},
|
||||||
|
Tagline: {
|
||||||
|
font: FONT_BOLD
|
||||||
|
},
|
||||||
|
Title: {
|
||||||
|
font: FONT_BOLD
|
||||||
|
},
|
||||||
|
Banner: {
|
||||||
|
font: FONT_BLACK
|
||||||
|
},
|
||||||
Button: {
|
Button: {
|
||||||
font: FONT_BOLD,
|
font: FONT_BOLD,
|
||||||
text_shadow: false,
|
text_shadow: false,
|
||||||
@@ -68,6 +100,7 @@ module W3DHubLauncher
|
|||||||
text_align: :left,
|
text_align: :left,
|
||||||
text_size: 24,
|
text_size: 24,
|
||||||
font: FONT_REGULAR,
|
font: FONT_REGULAR,
|
||||||
|
padding_left: HALF_PADDING
|
||||||
# background: 0xaa_000000,
|
# background: 0xaa_000000,
|
||||||
# border_color: 0xff_000000,
|
# border_color: 0xff_000000,
|
||||||
# hover: {
|
# hover: {
|
||||||
@@ -95,13 +128,24 @@ module W3DHubLauncher
|
|||||||
background: 0xee_444444
|
background: 0xee_444444
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Progress: {
|
||||||
|
height: NINE_SLICE_EDGE_TINY * 2,
|
||||||
|
background: 0,
|
||||||
|
background_nine_slice: NINE_SLICE_ROUNDED_TINY,
|
||||||
|
background_nine_slice_from_edge: NINE_SLICE_EDGE_TINY,
|
||||||
|
background_nine_slice_mode: :stretched,
|
||||||
|
background_nine_slice_color: 0x88_5e5c64,
|
||||||
|
fraction_background: 0xff_1a5fb4,
|
||||||
|
border_thickness: 0,
|
||||||
|
},
|
||||||
ToolTip: {
|
ToolTip: {
|
||||||
|
delay: 500,
|
||||||
text_size: 24,
|
text_size: 24,
|
||||||
background: 0,#x88_5e5c64,
|
background: 0,#x88_5e5c64,
|
||||||
background_nine_slice: NINE_SLICE_ROUNDED,
|
background_nine_slice: NINE_SLICE_ROUNDED,
|
||||||
background_nine_slice_from_edge: NINE_SLICE_EDGE,
|
background_nine_slice_from_edge: NINE_SLICE_EDGE,
|
||||||
background_nine_slice_mode: :stretched,
|
background_nine_slice_mode: :stretched,
|
||||||
background_nine_slice_color: 0xdd_5e5c64,
|
background_nine_slice_color: 0xcc_000000,
|
||||||
border_thickness: 0
|
border_thickness: 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module W3DHubLauncher
|
module W3DHubLauncher
|
||||||
NAME = "Cyberarm's W3D Hub linux Launcher".freeze
|
NAME = "Cyberarm's W3D Hub Linux Launcher".freeze
|
||||||
VERSION = "2.0.0".freeze
|
VERSION = "2.0.0".freeze
|
||||||
VERSION_NAME = "alpha".freeze # TODO: Come up with a short, fun, release name
|
VERSION_NAME = "alpha".freeze # TODO: Come up with a short, fun, release name
|
||||||
end
|
end
|
||||||
|
|||||||
182
lib/window.rb
182
lib/window.rb
@@ -4,186 +4,12 @@ module W3DHubLauncher
|
|||||||
self.show_cursor = true
|
self.show_cursor = true
|
||||||
self.caption = format("%s | v%s (%s)", NAME, VERSION, VERSION_NAME) # "Cyberarm's W3D Hub Linux Launcher | v2.0.0 alpha"
|
self.caption = format("%s | v%s (%s)", NAME, VERSION, VERSION_NAME) # "Cyberarm's W3D Hub Linux Launcher | v2.0.0 alpha"
|
||||||
|
|
||||||
push_state(Interface)
|
push_state(States::Boot)
|
||||||
|
# push_state(States::Interface)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
class Interface < CyberarmEngine::GuiState
|
def needs_redraw?
|
||||||
include W3DHubLauncher::GuiExt
|
states.any?(&:needs_repaint?)
|
||||||
|
|
||||||
def setup
|
|
||||||
theme(THEME)
|
|
||||||
|
|
||||||
# root container - background image
|
|
||||||
stack(width: 1.0, height: 1.0, background_image: safe_get_image("/run/media/cyberarm/Storage/W3DHub/Launcher/package-cache/games/apb/background.png.package"), background_image_mode: :fill) do
|
|
||||||
# root container - background image tint
|
|
||||||
flow(width: 1.0, height: 1.0, background: 0xaa_000000) do
|
|
||||||
# content container
|
|
||||||
stack(fill: true, height: 1.0, margin: PADDING, margin_right: LARGE_PADDING) do
|
|
||||||
# header bar container
|
|
||||||
flow(width: 1.0, height: 80, margin_bottom: PADDING) do |c|
|
|
||||||
# logo + menu button
|
|
||||||
button(safe_get_image("./media/logo.png"), image_height: 1.0, background: 0, border_color: 0, hover: { background: 0 }, active: { background: 0, color: 0xff_ffffff }) do |btn|
|
|
||||||
menu(parent: btn) do
|
|
||||||
menu_item("Settings")
|
|
||||||
menu_item("About")
|
|
||||||
menu_item("Exit") do
|
|
||||||
window.close
|
|
||||||
end
|
|
||||||
end.show
|
|
||||||
end
|
|
||||||
|
|
||||||
stack(fill: true, height: 1.0) do
|
|
||||||
stack(fill: true)
|
|
||||||
flow(width: 1.0) do
|
|
||||||
link "GAMES", text_v_align: :center, font: FONT_BLACK, margin_left: PADDING
|
|
||||||
link "SERVERS", text_v_align: :center, font: FONT_BLACK, margin_left: PADDING
|
|
||||||
stack(fill: true)
|
|
||||||
image safe_get_image("./media/icons/import.png"), height: 40, color: 0xff_bbbbbb
|
|
||||||
image safe_get_image("./media/icons/information.png"), height: 40, color: 0xff_bbbbbb
|
|
||||||
end
|
|
||||||
stack(fill: true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# page content container
|
|
||||||
stack(width: 1.0, fill: true) do
|
|
||||||
# game bar container
|
|
||||||
flow(width: 1.0, height: 60) do
|
|
||||||
flow(width: 220, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_BLACK) do
|
|
||||||
flow(width: 1.0, height: 40, margin_left: PADDING, v_align: :center, h_align: :center) do
|
|
||||||
image safe_get_image("./media/icons/menuGrid.png"), height: 40, color: 0xff_bbbbbb
|
|
||||||
link "ALL GAMES", text_size: 24, font: FONT_BLACK, height: 1.0, text_v_align: :center
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
flow(fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_BLACK, margin_left: PADDING) do
|
|
||||||
image safe_get_image("./data/cache/apb.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0x88_5e5c64, border_thickness_bottom: 3, border_color_bottom: 0xff_3584e4, tip: "Red Alert: A Path Beyond"
|
|
||||||
image safe_get_image("./data/cache/ren.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Command & Conquer: Renegade"
|
|
||||||
image safe_get_image("./data/cache/tsr.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Tiberian Sun: Reborn"
|
|
||||||
image safe_get_image("./data/cache/woa.png"), height: 1.0, padding: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0, tip: "Battle for Dune: War of Assassins"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# game content container
|
|
||||||
flow(width: 1.0, fill: true, margin_top: LARGE_PADDING) do
|
|
||||||
# game info container
|
|
||||||
stack(width: 340, height: 1.0) do
|
|
||||||
# logo
|
|
||||||
image safe_get_image("/run/media/cyberarm/Storage/W3DHub/Launcher/package-cache/games/apb/logo.png.package"), width: 1.0, max_height: 124
|
|
||||||
|
|
||||||
# web links
|
|
||||||
stack(width: 1.0, fill: true, padding: 0, padding_top: LARGE_PADDING) do
|
|
||||||
link "Modifications", text_size: 24
|
|
||||||
link "Bug Tracker", text_size: 24
|
|
||||||
link "Player Statistics", text_size: 24
|
|
||||||
end
|
|
||||||
|
|
||||||
# launching ta game
|
|
||||||
caption "Game Version"
|
|
||||||
list_box items: [ "Release", "Open Testing" ], width: 1.0, margin_bottom: PADDING
|
|
||||||
flow(width: 1.0, height: 60) do
|
|
||||||
button "PLAY", fill: true, height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_LEFT, **CTA_BUTTON_THEME
|
|
||||||
button safe_get_image("./media/icons/singleplayer.png"), image_height: 1.0, background_nine_slice: NINE_SLICE_SQUARE, **CTA_BUTTON_THEME
|
|
||||||
button safe_get_image("./media/icons/gear.png"), image_height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_RIGHT, **CTA_BUTTON_THEME
|
|
||||||
end
|
|
||||||
inscription "Version: 3.9.2.15", margin_top: PADDING
|
|
||||||
end
|
|
||||||
|
|
||||||
# game events and news container
|
|
||||||
stack(fill: true, height: 1.0, margin_left: LARGE_PADDING, scroll: true) do
|
|
||||||
flow(width: 1.0, height: 1.0, max_height: 380, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_BLACK) do
|
|
||||||
image safe_get_image("./media/background.png"), fill: true, aspect_ratio: 16.0 / 9.0
|
|
||||||
|
|
||||||
stack(fill: true, height: 1.0, margin_left: PADDING) do
|
|
||||||
caption "Upcoming Event", color: 0xff_22aa11, font: FONT_BOLD
|
|
||||||
title "Red Alert: A Path Beyond Game Night", font: FONT_BOLD
|
|
||||||
tagline "July 11, 2028"
|
|
||||||
|
|
||||||
flow(fill: true)
|
|
||||||
|
|
||||||
button "Read More", margin_left: PADDING, margin_right: LARGE_PADDING, margin_bottom: PADDING, width: 1.0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# news container
|
|
||||||
flow(width: 1.0, margin_top: PADDING) do
|
|
||||||
9.times do
|
|
||||||
stack(width: 1.0 / 3, height: 345, aspect_ratio: 1, margin_left: HALF_PADDING, margin_right: HALF_PADDING, margin_bottom: PADDING) do
|
|
||||||
stack(width: 1.0, fill: true, background_image: safe_get_image("./media/background.png"), background_image_mode: :fill)
|
|
||||||
stack(width: 1.0, height: 1.0 / 3, padding: PADDING, v_align: :bottom, background_nine_slice: NINE_SLICE_ROUNDED_BOTTOM, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_BLACK, border_thickness_top: 1, border_color_top: Gosu::Color::BLACK) do
|
|
||||||
caption "NEWS", color: 0x88_ffffff, font: FONT_BOLD
|
|
||||||
tagline "A News Item Post A News Item Post", font: FONT_BOLD
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# battleview/friends container
|
|
||||||
stack(width: 300, height: 1.0, margin: PADDING, margin_left: 0) do
|
|
||||||
# self account container
|
|
||||||
flow(width: 1.0, height: 80) do
|
|
||||||
# self avatar container
|
|
||||||
stack(width: 80, height: 1.0, background_image: rounded_avatar(safe_get_image("./media/default.png"))) do
|
|
||||||
# self online state container
|
|
||||||
stack(width: 20, height: 20, v_align: :bottom, h_align: :right, background_image: safe_get_image("./media/ui/circle_small.png"), background_image_color: 0xff_26a269)
|
|
||||||
end
|
|
||||||
|
|
||||||
stack(fill: true, height: 1.0, margin_left: HALF_PADDING) do
|
|
||||||
flow(fill: true)
|
|
||||||
# self name
|
|
||||||
caption "moonsense715test", font: FONT_BLACK, text_wrap: :none
|
|
||||||
# self set online state
|
|
||||||
link "Online ▼", text_size: 18 do |l|
|
|
||||||
menu(parent: l) do
|
|
||||||
menu_item("Online")
|
|
||||||
menu_item("Do Not Disturb")
|
|
||||||
menu_item("Away")
|
|
||||||
menu_item("Invisible")
|
|
||||||
menu_item("Sign Out")
|
|
||||||
end.show
|
|
||||||
end
|
|
||||||
flow(fill: true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# friend management container
|
|
||||||
flow(width: 1.0, height: 60, margin_top: PADDING) do
|
|
||||||
flow(width: 1.0, v_align: :center) do
|
|
||||||
button safe_get_image("./media/icons/singleplayer.png"), image_height: 1.0
|
|
||||||
button safe_get_image("./media/icons/gear.png"), image_height: 1.0, margin_left: HALF_PADDING
|
|
||||||
edit_line "", margin_left: HALF_PADDING, fill: true, height: 1.0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# friends/clanmates list container
|
|
||||||
stack(width: 1.0, fill: true, margin_top: LARGE_PADDING, scroll: true) do
|
|
||||||
50.times do |i|
|
|
||||||
# friend container
|
|
||||||
flow(width: 1.0, height: 48, padding_top: HALF_PADDING, padding_bottom: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_color: 0, hover: { background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0x44_000000 }) do
|
|
||||||
# friend avatar container
|
|
||||||
stack(width: 48, height: 1.0, margin_left: HALF_PADDING, background_image: rounded_avatar(safe_get_image("./media/default.png"))) do
|
|
||||||
stack(width: 12, height: 12, v_align: :bottom, h_align: :right, background_image: safe_get_image("./media/ui/circle_small.png"), background_image_color: 0xff_26a269)
|
|
||||||
end
|
|
||||||
# friend name and status container
|
|
||||||
stack(fill: true, height: 1.0, margin_left: HALF_PADDING, margin_right: HALF_PADDING) do
|
|
||||||
stack(v_align: :center) do
|
|
||||||
caption "moonsense#{715 * (i + 1) % 1000}test", font: FONT_BOLD, text_wrap: :none, text_size: 20
|
|
||||||
inscription "RA_Under • 13:52", text_wrap: :none, text_size: 14, margin_top: -HALF_PADDING
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# friend active application container
|
|
||||||
stack(width: 48, height: 1.0, margin_right: HALF_PADDING, background_image: safe_get_image("./media/logo.png"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
module W3DHubLauncher
|
module W3DHubLauncher
|
||||||
class Worker
|
class Worker
|
||||||
|
Response = Data.define(:status, :request_id, :data)
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@threads = []
|
@threads = []
|
||||||
|
@requests = []
|
||||||
|
|
||||||
|
@settings = # Settings.new
|
||||||
|
|
||||||
|
# next available request_id to assign incoming requests
|
||||||
|
@request_id = 0
|
||||||
|
|
||||||
# listen for requests from frontend
|
# listen for requests from frontend
|
||||||
listener = Thread.new { listen }
|
listener = Thread.new { listen }
|
||||||
@@ -10,15 +18,35 @@ module W3DHubLauncher
|
|||||||
# connect to and monitor Backend web service
|
# connect to and monitor Backend web service
|
||||||
@threads << Thread.new { backend_websocket }
|
@threads << Thread.new { backend_websocket }
|
||||||
|
|
||||||
Ractor.main.send({ message: "3 o'clock 'nd all's well!" })
|
@w3dhub_api = W3DHubLauncher::W3DHubApi.new
|
||||||
|
|
||||||
listener.join
|
listener.join
|
||||||
end
|
end
|
||||||
|
|
||||||
def listen
|
def listen
|
||||||
loop do
|
loop do
|
||||||
request = Ractor.receive
|
query = Ractor.receive
|
||||||
pp request
|
pp query
|
||||||
|
|
||||||
|
case query.type
|
||||||
|
when Request::FETCH_URL
|
||||||
|
when Request::DOWNLOAD_URL
|
||||||
|
when Request::W3DHUB_API_CALL
|
||||||
|
Async do
|
||||||
|
result = @w3dhub_api.send(query.data[:call], *(query.data[:arguments] || []))
|
||||||
|
response = Response.new(result.okay? ? Request::STATUS_COMPLETE : Request::STATUS_ERROR, query.request_id, result)
|
||||||
|
Ractor.main.send(response)
|
||||||
|
end
|
||||||
|
when Request::LAUNCHER_UPDATE_SETTINGS
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
FileUtils.mkdir_p(W3DHubLauncher::CONFIG_PATH) # FAILABLE!
|
||||||
|
File.write("#{W3DHubLauncher::CONFIG_PATH}/settings.json", query.data) # FAILABLE!
|
||||||
|
result.data = query.data
|
||||||
|
response = Response.new(result.okay? ? Request::STATUS_COMPLETE : Request::STATUS_ERROR, query.request_id, result)
|
||||||
|
Ractor.main.send(response)
|
||||||
|
else
|
||||||
|
raise "UNKNOWN REQUEST"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,76 +3,71 @@
|
|||||||
module W3DHubLauncher
|
module W3DHubLauncher
|
||||||
class Worker
|
class Worker
|
||||||
class Api
|
class Api
|
||||||
Request = Data.define(:coming_soon)
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@requests = []
|
|
||||||
end
|
|
||||||
|
|
||||||
# downloads requested resource, returns raw string
|
# downloads requested resource, returns raw string
|
||||||
def fetch_url
|
def self.fetch_url
|
||||||
end
|
end
|
||||||
|
|
||||||
# downloads requested resource, periodically reporting progress until completion, returning path for file on disk
|
# downloads requested resource, periodically reporting progress until completion, returning path for file on disk
|
||||||
def download_url
|
def self.download_url
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns user account data
|
# returns user account data
|
||||||
#
|
#
|
||||||
# automatically handles signing in / refreshing token (DOES NOT remove account data if failed to refresh token due to network timeout)
|
# automatically handles signing in / refreshing token (DOES NOT remove account data if failed to refresh token due to network timeout)
|
||||||
def account
|
def self.account
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns launcher settings
|
# returns launcher settings
|
||||||
def settings
|
def self.settings
|
||||||
end
|
end
|
||||||
|
|
||||||
# write updated launcher settings
|
# write updated launcher settings
|
||||||
def update_settings
|
def self.update_settings(settings, &block)
|
||||||
|
Worker::Request.new(Request::LAUNCHER_UPDATE_SETTINGS, settings.to_json, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns list of available applications
|
# returns list of available applications
|
||||||
#
|
#
|
||||||
# if updated list is requested, return cached version immediately and then the updated list later.
|
# if updated list is requested, return cached version immediately and then the updated list later.
|
||||||
def applications
|
def self.applications
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns current list of servers as reported from GSH / cache
|
# returns current list of servers as reported from GSH / cache
|
||||||
def servers
|
def self.servers
|
||||||
end
|
end
|
||||||
|
|
||||||
# returns news for application
|
# returns news for application
|
||||||
def news
|
def self.news
|
||||||
end
|
end
|
||||||
|
|
||||||
# request installation of application
|
# request installation of application
|
||||||
#
|
#
|
||||||
# periodically reports progress until completion
|
# periodically reports progress until completion
|
||||||
def install_application
|
def self.install_application
|
||||||
end
|
end
|
||||||
|
|
||||||
# request update of application
|
# request update of application
|
||||||
#
|
#
|
||||||
# periodically reports progress until completion
|
# periodically reports progress until completion
|
||||||
def update_application
|
def self.update_application
|
||||||
end
|
end
|
||||||
|
|
||||||
# request repair of application
|
# request repair of application
|
||||||
#
|
#
|
||||||
# periodically reports progress until completion
|
# periodically reports progress until completion
|
||||||
def repair_application
|
def self.repair_application
|
||||||
end
|
end
|
||||||
|
|
||||||
# request relocation of application
|
# request relocation of application
|
||||||
#
|
#
|
||||||
# periodically reports progress until completion
|
# periodically reports progress until completion
|
||||||
def move_application
|
def self.move_application
|
||||||
end
|
end
|
||||||
|
|
||||||
# request removal of application
|
# request removal of application
|
||||||
#
|
#
|
||||||
# periodically reports progress until completion
|
# periodically reports progress until completion
|
||||||
def uninstall_application
|
def self.uninstall_application
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
65
lib/worker/request.rb
Normal file
65
lib/worker/request.rb
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class Worker
|
||||||
|
class Request
|
||||||
|
Query = Data.define(:type, :request_id, :data)
|
||||||
|
|
||||||
|
FETCH_URL = 0
|
||||||
|
DOWNLOAD_URL = 1
|
||||||
|
W3DHUB_API_CALL = 10
|
||||||
|
LAUNCHER_SETTINGS = 1000
|
||||||
|
LAUNCHER_UPDATE_SETTINGS = 1001
|
||||||
|
|
||||||
|
STATUS_ERROR = -1 # request has failed
|
||||||
|
STATUS_PENDING = 0 # request has not yet started
|
||||||
|
STATUS_OK = 1 # request completed successfully
|
||||||
|
STATUS_COMPLETE = STATUS_OK
|
||||||
|
STATUS_IN_PROGRESS = 2 # request is in progress
|
||||||
|
STATUS_BUSY = STATUS_IN_PROGRESS
|
||||||
|
|
||||||
|
# NOT "Thread"/Ractor safe
|
||||||
|
@request_id = 0
|
||||||
|
@requests = []
|
||||||
|
|
||||||
|
# NOT "Thread"/Ractor safe. Only call from main ractor
|
||||||
|
# returns next available request id, and auto increments by 1
|
||||||
|
def self.request_id
|
||||||
|
@request_id += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# NOT "Thread"/Ractor safe.
|
||||||
|
# returns an array of pending requests
|
||||||
|
def self.requests
|
||||||
|
@requests
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :type, :data, :request_id
|
||||||
|
|
||||||
|
def initialize(type, data, request_id: Request.request_id, &block)
|
||||||
|
@type = type.freeze
|
||||||
|
@data = data.freeze
|
||||||
|
@status = STATUS_PENDING
|
||||||
|
|
||||||
|
@request_id = request_id
|
||||||
|
@callback = block # only called on error or success
|
||||||
|
|
||||||
|
enqueue(@type, @request_id, @data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def enqueue(type, id, data)
|
||||||
|
Request.requests << self
|
||||||
|
W3DHubLauncher::WORKER.send(Query.new(type, id, data))
|
||||||
|
end
|
||||||
|
|
||||||
|
# event from Worker received
|
||||||
|
def handle_event(event, data)
|
||||||
|
pp [event, data]
|
||||||
|
|
||||||
|
case event
|
||||||
|
when STATUS_ERROR, STATUS_COMPLETE
|
||||||
|
@callback&.call(data)
|
||||||
|
Request.requests.delete(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
module W3DHubLauncher
|
||||||
|
class W3DHubApi
|
||||||
|
API_TIMEOUT = 30 # seconds
|
||||||
|
API_CONNECT_TIMEOUT = 10 # seconds
|
||||||
|
|
||||||
|
PRIMARY_W3DHUB_API_ENDPOINT = "https://secure.w3dhub.com".freeze
|
||||||
|
ALTERNATIVE_W3DHUB_API_ENDPOINT = "https://backend.w3d.cyberarm.dev".freeze
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@access_token = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def headers(form_encoded: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
# return raw response to requester
|
||||||
|
def fetch(url, method: :get, body: nil, headers: headers())
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
|
||||||
|
Sync do |task|
|
||||||
|
task.with_timeout(API_TIMEOUT) do
|
||||||
|
Async::HTTP::Internet.send(method, url, headers, body) do |response|
|
||||||
|
result.data = response.read
|
||||||
|
rescue StandardError => e
|
||||||
|
result.error = e
|
||||||
|
end
|
||||||
|
rescue Async::TimeoutError
|
||||||
|
result.error = e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
# write response to file, periodically reporting progress to requester
|
||||||
|
def download(url, path:, method: :get, body: nil, headers: headers(), &block)
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
|
||||||
|
Sync do |task|
|
||||||
|
task.with_timeout(API_TIMEOUT) do
|
||||||
|
Async::HTTP::Internet.send(method, url, headers, body) do |response|
|
||||||
|
if response.success?
|
||||||
|
content_length = response.headers["content-length"] || 0
|
||||||
|
|
||||||
|
total_downloaded_bytes = 0
|
||||||
|
File.open(path, "wb") do |file|
|
||||||
|
response.each do |chunk|
|
||||||
|
file.write(chunk)
|
||||||
|
downloaded_bytes = chunk.length
|
||||||
|
total_downloaded_bytes += downloaded_bytes
|
||||||
|
|
||||||
|
block&.call(downloaded_bytes, total_downloaded_bytes, content_length)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result.data = true
|
||||||
|
end
|
||||||
|
rescue StandardError => e
|
||||||
|
result.error = e
|
||||||
|
end
|
||||||
|
rescue Async::TimeoutError
|
||||||
|
result.error = e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_login()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh_user_login()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_user_details()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_applications
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_news()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_events()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_manifest()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_manifests()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_package_details()
|
||||||
|
result = CyberarmEngine::Result.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def fetch_package()
|
||||||
|
download()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
BIN
media/ui/rounded_small.png
Normal file
BIN
media/ui/rounded_small.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 212 B |
BIN
media/ui/rounded_tiny.png
Normal file
BIN
media/ui/rounded_tiny.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 173 B |
@@ -4,13 +4,44 @@ rescue LoadError
|
|||||||
require "cyberarm_engine"
|
require "cyberarm_engine"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require "rexml"
|
||||||
|
require "base64"
|
||||||
|
require "logger"
|
||||||
|
|
||||||
|
require "async"
|
||||||
|
require "async/http/internet/instance"
|
||||||
|
require "async/websocket"
|
||||||
|
require "digest/crc"
|
||||||
|
require "ircparser"
|
||||||
|
require "zip"
|
||||||
|
|
||||||
require_relative "lib/version"
|
require_relative "lib/version"
|
||||||
|
require_relative "lib/constants"
|
||||||
|
require_relative "lib/attribution"
|
||||||
require_relative "lib/gui_ext"
|
require_relative "lib/gui_ext"
|
||||||
|
require_relative "lib/state"
|
||||||
|
require_relative "lib/dialog"
|
||||||
require_relative "lib/theme"
|
require_relative "lib/theme"
|
||||||
|
require_relative "lib/pages/games"
|
||||||
|
require_relative "lib/pages/server_browser"
|
||||||
|
require_relative "lib/pages/boot/terms"
|
||||||
|
require_relative "lib/pages/boot/initial_setup"
|
||||||
|
require_relative "lib/pages/boot/start_up"
|
||||||
|
require_relative "lib/dialogs/about"
|
||||||
|
require_relative "lib/dialogs/downloads"
|
||||||
|
require_relative "lib/states/boot"
|
||||||
|
require_relative "lib/states/interface"
|
||||||
require_relative "lib/window"
|
require_relative "lib/window"
|
||||||
|
|
||||||
require_relative "lib/worker"
|
require_relative "lib/worker"
|
||||||
require_relative "lib/worker/api"
|
require_relative "lib/worker/api"
|
||||||
|
require_relative "lib/worker/request"
|
||||||
|
require_relative "lib/worker/w3dhub_api"
|
||||||
|
require_relative "lib/worker/task"
|
||||||
|
require_relative "lib/worker/tasks/install_application"
|
||||||
|
require_relative "lib/worker/tasks/uninstall_application"
|
||||||
|
require_relative "lib/worker/tasks/repair_application"
|
||||||
|
require_relative "lib/worker/tasks/update_application"
|
||||||
|
|
||||||
module W3DHubLauncher
|
module W3DHubLauncher
|
||||||
WORKER = Ractor.new(name: "Parallel Worker") { W3DHubLauncher::Worker.new }
|
WORKER = Ractor.new(name: "Parallel Worker") { W3DHubLauncher::Worker.new }
|
||||||
@@ -25,11 +56,20 @@ end
|
|||||||
# NOTE: May need to mangle Window#update to do ruby-land sleep so thread gets time to process :(
|
# NOTE: May need to mangle Window#update to do ruby-land sleep so thread gets time to process :(
|
||||||
Thread.new do
|
Thread.new do
|
||||||
loop do
|
loop do
|
||||||
message = Ractor.receive
|
response = Ractor.receive
|
||||||
pp message
|
pp response
|
||||||
|
|
||||||
|
request = W3DHubLauncher::Worker::Request.requests.find { |r| r.request_id == response.request_id }
|
||||||
|
request&.handle_event(response.status, response.data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# 10.times do
|
||||||
|
# W3DHubLauncher::Worker::Request.new(W3DHubLauncher::Worker::Request::W3DHUB_API_CALL, { call: :fetch_applications }) do |result|
|
||||||
|
# pp result
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
window = W3DHubLauncher::Window.new(width: 1280, height: 800, resizable: true)
|
window = W3DHubLauncher::Window.new(width: 1280, height: 800, resizable: true)
|
||||||
# window = W3DHubLauncher::Window.new(width: 1920, height: 1080, resizable: true)
|
# window = W3DHubLauncher::Window.new(width: 1920, height: 1080, resizable: true)
|
||||||
window.show
|
window.show
|
||||||
|
|||||||
Reference in New Issue
Block a user