Initial pass of fetching and using application news, server events, server ping display now shows unit (ms) instead of just the number- also helps with confusing it for player count

This commit is contained in:
2026-09-09 23:38:40 -05:00
parent 0693733179
commit b0fefb9f7f
9 changed files with 146 additions and 32 deletions

View File

@@ -30,12 +30,19 @@ module W3DHubLauncher
# game events and news container # game events and news container
stack(fill: true, height: 1.0, margin_left: LARGE_PADDING, scroll: true) do stack(fill: true, height: 1.0, margin_left: LARGE_PADDING, scroll: true) do
@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 @event_container = stack(width: 1.0, padding: PADDING, margin_left: HALF_PADDING, margin_right: HALF_PADDING, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: 0x88_26a269) do
end end
# news container # news container
@news_container = flow(width: 1.0, margin_top: PADDING) do @news_container = flow(width: 1.0, margin_top: PADDING) do
end end
# "dynamically" adjust news item widths
@news_container.subscribe(:size_changed) do |event|
@news_container.children.each do |box|
box.style.width = 1.0 / news_item_width_ratio
end
end
end end
end end
@@ -62,6 +69,29 @@ module W3DHubLauncher
return return
end end
app_id = @current_app.id
unless MemCache[:"events_#{app_id}"]
Worker::Api.events(app_id) do |result|
if result.okay?
File.write("events_#{app_id}.json", result.data)
MemCache[:"events_#{app_id}"] = JSON.parse(result.data)&.map { |item| Worker::Api::ServerEvent.new(item) } || []
populate_game_event if app_id == @current_app.id
end
end
end
unless MemCache[:"news_#{app_id}"]
Worker::Api.news(app_id) do |result|
if result.okay?
File.write("news_#{app_id}.json", result.data)
MemCache[:"news_#{app_id}"] = JSON.parse(result.data)["news"]&.map { |item| Worker::Api::NewsItem.new(item) } || []
populate_game_news if app_id == @current_app.id
end
end
end
populate_games_list populate_games_list
populate_game_info populate_game_info
populate_game_event populate_game_event
@@ -80,8 +110,6 @@ module W3DHubLauncher
end end
end end
end end
puts
end end
end end
@@ -100,7 +128,9 @@ module W3DHubLauncher
# web links # web links
stack(width: 1.0, fill: true, padding: 0, padding_top: LARGE_PADDING) do stack(width: 1.0, fill: true, padding: 0, padding_top: LARGE_PADDING) do
@current_app.web_links.each do |link| @current_app.web_links.each do |link|
link link.name, text_size: 24, tip: link.uri link link.name, text_size: 24, tip: link.uri do
SDL.OpenURL(link.uri)
end
end end
end end
@@ -131,38 +161,48 @@ module W3DHubLauncher
end end
def populate_game_event def populate_game_event
# TODO: Hide event container if there is no event app_events = MemCache[:"events_#{@current_app.id}"] || []
@event_container.show if false if app_events.empty?
@event_container.hide if true @event_container.hide
else
@event_container.show
@event_container.clear do event = app_events.sort(&:start_time).last
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 @event_container.clear do
caption "Upcoming Event".upcase, color: 0xff_22aa11 caption "Upcoming Event".upcase, color: 0xaa_ffffff
title "Red Alert: A Path Beyond Game Night" tagline event.title # "Red Alert: A Path Beyond Game Night"
tagline "July 11, 2028" caption event.start_time.strftime("%B %e, %Y • %T") # "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 end
end end
def populate_game_news def populate_game_news
app_news = MemCache[:"news_#{@current_app.id}"] || []
@news_container.clear do @news_container.clear do
9.times do app_news.each do |item|
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 / news_item_width_ratio, height: 345, aspect_ratio: 1, margin_left: HALF_PADDING, margin_right: HALF_PADDING, margin_bottom: PADDING, background_nine_slice: NINE_SLICE_ROUNDED, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) 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, background_nine_slice: NINE_SLICE_ROUNDED_TOP, background_nine_slice_from_edge: NINE_SLICE_EDGE, background_nine_slice_color: ALPHA_GRAY) do
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 para item.timestamp.strftime("%B %e, %Y") #"September 29, 2026"
caption "NEWS", color: 0x88_ffffff tagline item.title
tagline "A News Item Post A News Item Post" end
stack(width: 1.0, fill: true, padding: PADDING, padding_bottom: 0, scroll: false) do
para item.blurb
end
button "Read More", margin: PADDING, width: 1.0, tip: item.uri do
SDL.OpenURL(item.uri)
end end
end end
end end
end end
end end
def news_item_width_ratio
(@news_container.width / 400.0).round.clamp(1..10)
end
end end
end end
end end

View File

@@ -97,7 +97,7 @@ module W3DHubLauncher
# server ping # server ping
flow(width: 96, height: 1.0, margin_left: HALF_PADDING, margin_right: HALF_PADDING) do 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 stack(fill: true, height: 1.0, v_align: :center) do
caption server.ping == Worker::Api::GameServer::BAD_OR_UNKNOWN_PING ? "?" : server.ping, width: 1.0, text_align: :center, tip: server.ping == Worker::Api::GameServer::BAD_OR_UNKNOWN_PING ? "Server has not replied yet or did not reply to ICMP Echo Request.\nPing unknown." : "" caption server.ping == Worker::Api::GameServer::BAD_OR_UNKNOWN_PING ? "?" : format("%ims", server.ping), width: 1.0, text_align: :center, tip: server.ping == Worker::Api::GameServer::BAD_OR_UNKNOWN_PING ? "Server has not replied yet or did not reply to ICMP Echo Request.\nPing unknown." : ""
inscription "ping", text_wrap: :none, width: 1.0, text_align: :center, margin_top: -HALF_PADDING inscription "ping", text_wrap: :none, width: 1.0, text_align: :center, margin_top: -HALF_PADDING
end end
stack(width: 8, height: server.ping_score_ratio, 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: server.ping_score_color) stack(width: 8, height: server.ping_score_ratio, 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: server.ping_score_color)

View File

@@ -54,12 +54,12 @@ module W3DHubLauncher
# returns news for application # returns news for application
def self.news(category = "launcher-home", &block) def self.news(category = "launcher-home", &block)
Worker::Request.new(:news, category, &block) W3DHubLauncher::Worker::Request.new(:w3dhub_api_call, { call: :fetch_news, arguments: [category] }, &block)
end end
# returns news for application # returns news for application
def self.events(app_id, &block) def self.events(category, &block)
Worker::Request.new(:events, app_id, &block) W3DHubLauncher::Worker::Request.new(:w3dhub_api_call, { call: :fetch_events, arguments: [category] }, &block)
end end
# request installation of application # request installation of application

View File

@@ -0,0 +1,28 @@
module W3DHubLauncher
class Worker
class Api
class NewsItem
attr_reader :topic_id, :title, :blurb, :uri, :image_uri, :author_id, :author, :author_uri, :timestamp
def initialize(data)
@topic_id = Integer(data["topic-id"] || 0)
@title = data["title"].to_s
@blurb = clean_and_scrub_blurb(data["blurb"].to_s)
@uri = data["uri"].to_s
@image_uri = data["image"].to_s
@author_id = data["author-id"].to_s
@author = data["author"].to_s
@author_uri = data["author-uri"].to_s
@timestamp = Time.at(Integer(data["timestamp"] || 0), in: "UTC").localtime
end
# Replaces multiple newlines with a single newline, and trims off any leading and trailing whitespace.
def clean_and_scrub_blurb(string)
string.gsub(/\n+/, "\n").strip
end
end
end
end
end

View File

@@ -0,0 +1,17 @@
module W3DHubLauncher
class Worker
class Api
class ServerEvent
attr_reader :title, :image_uri, :app_id, :start_time, :end_time, :timestamp
def initialize(data)
@title = data["title"]
@image_uri = data["image"]
@app_id = data["server"]
@start_time = Time.parse(data["starttime"], in: "UTC").localtime
@end_time = Time.parse(data["endtime"], in: "UTC").localtime
@timestamp = Time.parse(data["dateTime"], in: "UTC").localtime
end
end
end
end
end

View File

@@ -0,0 +1,19 @@
module W3DHubLauncher
class Worker
class Api
class TestEvent
attr_reader :title, :image_uri, :timestamp
def initialize(data)
@title = data["name"]
# @title = data["title"]
@image_uri = data["image"]
# @app_id = data["server"]
# @start_time = Time.parse(data["starttime"]).localtime
# @end_time = Time.parse(data["endtime"]).localtime
@timestamp = Time.parse(data["dateTime"], in: "UTC").localtime
end
end
end
end
end

View File

View File

@@ -33,10 +33,10 @@ module W3DHubLauncher
Sync do |task| Sync do |task|
task.with_timeout(API_TIMEOUT) do task.with_timeout(API_TIMEOUT) do
Async::HTTP::Internet.send(method, url, headers, body) do |response| Async::HTTP::Internet.send(method, url, headers, body) do |response|
# pp [method, url, headers, body]
if response.success? if response.success?
result.data = response.read result.data = response.read
else else
# pp response
result.error = true result.error = true
end end
end end
@@ -124,12 +124,16 @@ module W3DHubLauncher
result result
end end
def fetch_news() def fetch_news(category)
result = CyberarmEngine::Result.new fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/w3dhub/1/get-news", method: :post, body: "data={\"category\":\"#{category}\"}", headers: headers(form_encoded: true))
end end
def fetch_events() def fetch_events(category)
result = CyberarmEngine::Result.new fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/w3dhub/1/get-server-events", method: :post, body: "data={\"serverPath\":\"#{category}\"}", headers: headers(form_encoded: true))
end
def fetch_test_events(category)
fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/w3dhub/1/get-testing-times")
end end
def fetch_manifest() def fetch_manifest()

View File

@@ -51,6 +51,11 @@ require_relative "lib/worker/api"
require_relative "lib/worker/api/application" require_relative "lib/worker/api/application"
require_relative "lib/worker/api/game_server" require_relative "lib/worker/api/game_server"
require_relative "lib/worker/api/settings" require_relative "lib/worker/api/settings"
require_relative "lib/worker/api/news_item"
require_relative "lib/worker/api/server_event"
require_relative "lib/worker/api/test_event"
require_relative "lib/worker/api/legacy_manifest"
require_relative "lib/worker/api/legacy_manifest_package"
require_relative "lib/worker/request" require_relative "lib/worker/request"
require_relative "lib/worker/w3dhub_api" require_relative "lib/worker/w3dhub_api"
require_relative "lib/worker/task" require_relative "lib/worker/task"
@@ -58,6 +63,7 @@ require_relative "lib/worker/tasks/install_application"
require_relative "lib/worker/tasks/uninstall_application" require_relative "lib/worker/tasks/uninstall_application"
require_relative "lib/worker/tasks/repair_application" require_relative "lib/worker/tasks/repair_application"
require_relative "lib/worker/tasks/update_application" require_relative "lib/worker/tasks/update_application"
require_relative "lib/worker/tasks/move_application"
module W3DHubLauncher module W3DHubLauncher
MemCache = {} MemCache = {}