mirror of
https://github.com/cyberarm/w3d_hub_linux_launcher.git
synced 2026-09-19 06:43:55 +00:00
Initial work on using real data for Games page
This commit is contained in:
@@ -55,6 +55,17 @@ module W3DHubLauncher
|
||||
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
|
||||
puts "HELLO"
|
||||
W3DHubLauncher::Worker::Request.new(:w3dhub_api_call, { call: :fetch_applications }) do |result|
|
||||
pp [:CALLBACK, result]
|
||||
File.write("applications.json", result.data)
|
||||
hash = JSON.parse(result.data)
|
||||
pp applications = hash["applications"]&.map { |app| W3DHubLauncher::Worker::Api::Application.new(app) } || []
|
||||
pp applications.to_json
|
||||
|
||||
MemCache[:applications] = applications
|
||||
end
|
||||
|
||||
f.show
|
||||
@progress_bar.type = :linear
|
||||
@progress_bar.value = 0.0
|
||||
|
||||
@@ -4,6 +4,11 @@ module W3DHubLauncher
|
||||
include GuiExt
|
||||
|
||||
def setup
|
||||
@games = MemCache[:applications]&.select { |app| app.type.include?("game") } || []
|
||||
|
||||
@current_app = @games.first
|
||||
@current_channel = @current_app&.channels&.first
|
||||
|
||||
# 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
|
||||
@@ -13,65 +18,119 @@ module W3DHubLauncher
|
||||
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"
|
||||
@games_list_container = 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
|
||||
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("#{ROOT_PATH}/media/default.png"), 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
|
||||
@game_info_container = stack(width: 340, height: 1.0) do
|
||||
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
|
||||
@event_container = 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
|
||||
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
|
||||
@news_container = flow(width: 1.0, margin_top: PADDING) do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
populate_games_list
|
||||
populate_game_info
|
||||
populate_game_event
|
||||
populate_game_news
|
||||
end
|
||||
|
||||
def populate_games_list
|
||||
@games_list_container.clear do
|
||||
@games.each_with_index do |game, i|
|
||||
if i.zero?
|
||||
image(safe_get_image("#{ROOT_PATH}/data/cache/#{game.id}.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: game.name)do
|
||||
@current_app = game
|
||||
@current_channel = game&.channels&.first
|
||||
|
||||
populate_games_list
|
||||
populate_game_info
|
||||
populate_game_event
|
||||
populate_game_news
|
||||
end
|
||||
else
|
||||
image(safe_get_image("#{ROOT_PATH}/data/cache/#{game.id}.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: game.name)do
|
||||
@current_app = game
|
||||
@current_channel = game&.channels&.first
|
||||
|
||||
populate_games_list
|
||||
populate_game_info
|
||||
populate_game_event
|
||||
populate_game_news
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def populate_game_info
|
||||
@game_info_container.clear do
|
||||
# logo
|
||||
image safe_get_image("#{ROOT_PATH}/media/#{@current_app.id}.png"), width: 1.0, max_height: 124
|
||||
|
||||
# web links
|
||||
stack(width: 1.0, fill: true, padding: 0, padding_top: LARGE_PADDING) do
|
||||
@current_app.web_links.each do |link|
|
||||
link link.name, text_size: 24, tip: link.uri
|
||||
end
|
||||
end
|
||||
|
||||
# launching ta game
|
||||
if (@current_app&.channels&.size || 0) > 1
|
||||
caption "Game Version"
|
||||
list_box(items: @current_app.channels.map(&:name), choose: @current_channel&.name, width: 1.0, margin_bottom: PADDING) do |item|
|
||||
@current_channel = @current_app.channels.find { |c| c.name == item }
|
||||
populate_game_info
|
||||
end
|
||||
end
|
||||
flow(width: 1.0, height: 60) do
|
||||
button "JOIN", tip: "Join most populated or lowest ping server", 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"), tip: "Single player", image_height: 1.0, background_nine_slice: NINE_SLICE_SQUARE, **CTA_BUTTON_THEME
|
||||
button safe_get_image("#{ROOT_PATH}/media/icons/gear.png"), tip: "Options", image_height: 1.0, background_nine_slice: NINE_SLICE_ROUNDED_RIGHT, **CTA_BUTTON_THEME
|
||||
end
|
||||
# FIXME: the reported version should be the _installed_ version, not the current channel version
|
||||
inscription "Version: #{@current_channel.version}", margin_top: PADDING, tip: "Installed version"
|
||||
end
|
||||
end
|
||||
|
||||
def populate_game_event
|
||||
# TODO: Hide event container if there is no event
|
||||
@event_container.show if false
|
||||
@event_container.hide if true
|
||||
|
||||
@event_container.clear 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
|
||||
end
|
||||
|
||||
def populate_game_news
|
||||
@news_container.clear 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
|
||||
|
||||
@@ -77,6 +77,8 @@ module W3DHubLauncher
|
||||
text_shadow: false,
|
||||
color: 0xff_ffffff,
|
||||
background: 0,#x88_5e5c64,
|
||||
padding_left: HALF_PADDING,
|
||||
padding_right: HALF_PADDING,
|
||||
background_nine_slice: NINE_SLICE_ROUNDED,
|
||||
background_nine_slice_from_edge: NINE_SLICE_EDGE,
|
||||
background_nine_slice_mode: :stretched,
|
||||
|
||||
@@ -36,17 +36,18 @@ module W3DHubLauncher
|
||||
UNIXServer.open(IPC_PATH) do |server|
|
||||
while(socket = server.accept)
|
||||
task.async do
|
||||
data = socket.gets
|
||||
json = JSON.parse(data)
|
||||
query = Request::Query.new(type: json["type"].to_sym, request_id: json["request_id"], data: json["data"])
|
||||
while(data =socket.gets)
|
||||
json = JSON.parse(data)
|
||||
query = Request::Query.new(type: json["type"].to_sym, request_id: json["request_id"], data: json["data"])
|
||||
|
||||
pp [:server_incoming, data, query]
|
||||
pp [:server_incoming, data, query]
|
||||
|
||||
if respond_to?(query.type)
|
||||
response = send(query.type, query)
|
||||
pp [:server_to_client, response]
|
||||
payload = { status: response.status, request_id: response.request_id, data: response.data.data }.to_json
|
||||
socket.puts(payload)
|
||||
if respond_to?(query.type)
|
||||
response = send(query.type, query)
|
||||
pp [:server_to_client, response]
|
||||
payload = { status: response.status, request_id: response.request_id, data: response.data.data }.to_json
|
||||
socket.puts(payload)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
92
lib/worker/api/application.rb
Normal file
92
lib/worker/api/application.rb
Normal file
@@ -0,0 +1,92 @@
|
||||
module W3DHubLauncher
|
||||
class Worker
|
||||
class Api
|
||||
class Application
|
||||
attr_reader :id, :category, :name, :type, :channels, :extended_data, :web_links
|
||||
|
||||
def initialize(data)
|
||||
pp data
|
||||
|
||||
@id = data["id"]
|
||||
@category = data["category"]
|
||||
@name = data["name"]
|
||||
@type = data["type"]
|
||||
|
||||
@channels = data["channels"]&.map { |c| Channel.new(c) } || []
|
||||
|
||||
@extended_data = data["extended-data"]&.map { |d| ExtendedData.new(d) } || nil
|
||||
@web_links = data["web-links"]&.map { |d| WebLink.new(d) } || nil
|
||||
end
|
||||
|
||||
# libgosu friendly color
|
||||
def color
|
||||
"ff_#{(@extended_data["colour"] || "#000000").sub("#", "")}".to_i(16)
|
||||
end
|
||||
|
||||
def to_json(context = nil)
|
||||
{
|
||||
"id": @id,
|
||||
"category": @category,
|
||||
"name": @name,
|
||||
"type": @type,
|
||||
"channels": @channels,
|
||||
"extended-data": @extended_data,
|
||||
"web-links": @web_links
|
||||
}.to_json(context)
|
||||
end
|
||||
|
||||
class Channel
|
||||
attr_reader :id, :name, :user_level, :version
|
||||
|
||||
def initialize(data)
|
||||
@id = data["id"]
|
||||
@name = data["name"]
|
||||
@user_level = data["user-level"]
|
||||
@version = Gem::Version.new(data["current-version"])
|
||||
end
|
||||
|
||||
def to_json(context = nil)
|
||||
{
|
||||
"id": @id,
|
||||
"name": @name,
|
||||
"user-level": @user_level,
|
||||
"current-version": @version.to_s
|
||||
}.to_json(context)
|
||||
end
|
||||
end
|
||||
|
||||
class ExtendedData
|
||||
attr_reader :name, :value
|
||||
|
||||
def initialize(data)
|
||||
@name = data["name"]
|
||||
@value = data["value"]
|
||||
end
|
||||
|
||||
def to_json(context = nil)
|
||||
{
|
||||
"name": @name,
|
||||
"value": @value
|
||||
}.to_json(context)
|
||||
end
|
||||
end
|
||||
|
||||
class WebLink
|
||||
attr_reader :name, :uri
|
||||
|
||||
def initialize(data)
|
||||
@name = data["name"]
|
||||
@uri = data["uri"]
|
||||
end
|
||||
|
||||
def to_json(context = nil)
|
||||
{
|
||||
"name": @name,
|
||||
"uri": @uri
|
||||
}.to_json(context)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -36,6 +36,7 @@ require_relative "lib/window"
|
||||
|
||||
require_relative "lib/worker"
|
||||
require_relative "lib/worker/api"
|
||||
require_relative "lib/worker/api/application"
|
||||
require_relative "lib/worker/request"
|
||||
require_relative "lib/worker/w3dhub_api"
|
||||
require_relative "lib/worker/task"
|
||||
@@ -45,6 +46,8 @@ require_relative "lib/worker/tasks/repair_application"
|
||||
require_relative "lib/worker/tasks/update_application"
|
||||
|
||||
module W3DHubLauncher
|
||||
MemCache = {}
|
||||
|
||||
# UNIXServer
|
||||
Thread.new do
|
||||
W3DHubLauncher::Worker.new.listen
|
||||
@@ -55,12 +58,6 @@ module W3DHubLauncher
|
||||
WORKER.connect
|
||||
end
|
||||
|
||||
# 10.times do
|
||||
# W3DHubLauncher::Worker::Request.new(:w3dhub_api_call, { call: :fetch_applications }) do |result|
|
||||
# pp [:CALLBACK, result]
|
||||
# end
|
||||
# end
|
||||
|
||||
window = W3DHubLauncher::Window.new(width: 1280, height: 800, resizable: true)
|
||||
# window = W3DHubLauncher::Window.new(width: 1920, height: 1080, resizable: true)
|
||||
window.show
|
||||
|
||||
Reference in New Issue
Block a user