diff --git a/lib/pages/server_browser.rb b/lib/pages/server_browser.rb index 21fefcb..8f621ba 100644 --- a/lib/pages/server_browser.rb +++ b/lib/pages/server_browser.rb @@ -6,6 +6,8 @@ module W3DHubLauncher def setup @games_filter = [] + CyberarmEngine::EventBus.subscribe("game_server_pings", self, :handle_game_server_pings) + # game bar container flow(width: 1.0, height: 60) do widget(width: 220, height: 1.0, style_class: [:all_button]) do |w| @@ -49,9 +51,17 @@ module W3DHubLauncher populate_server_list end + def blur + CyberarmEngine::EventBus.unsubscribe("game_server_pings", self) + end + + def handle_game_server_pings(payload) + # TODO: Update displayed server ping + end + def populate_server_list @servers_container.clear do - (MemCache[:servers] || []).select { |s| @games_filter.empty? ? true : @games_filter.include?(s.game) }.sort_by { |s| s.player_count }.reverse.each do |server| + (MemCache[:servers] || []).select { |s| @games_filter.empty? ? true : @games_filter.include?(s.game) }.sort_by { |s| [s.player_count, -s.ping] }.reverse.each do |server| app = MemCache[:applications].find { |a| a.id == server.game } 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: server.channel == "release" ? ALPHA_GRAY : 0xaa_c64600, hover: { background_nine_slice_color: 0xff_5e5c64 } , active: { background_nine_slice_color: 0xaa_5e5c64 }) do @@ -87,10 +97,10 @@ module W3DHubLauncher # 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 + 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." : "" 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) + 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) end end end diff --git a/lib/window.rb b/lib/window.rb index 28ca957..ef01d4b 100644 --- a/lib/window.rb +++ b/lib/window.rb @@ -6,6 +6,10 @@ module W3DHubLauncher @main_thread_queue = [] + CyberarmEngine::EventBus.subscribe("game_server_pings", self) do |payload| + MemCache[:game_server_pings] = payload + end + push_state(States::Boot) # push_state(States::Interface) end diff --git a/lib/worker.rb b/lib/worker.rb index 90bf5f9..ff6fef0 100644 --- a/lib/worker.rb +++ b/lib/worker.rb @@ -30,6 +30,8 @@ module W3DHubLauncher @threads = [] @requests = [] + @client = nil + @settings = 0# Settings.new @game_servers = [] @host_pings = {} @@ -46,6 +48,8 @@ module W3DHubLauncher Async do |task| UNIXServer.open(IPC_PATH) do |server| while(socket = server.accept) + @client = socket + task.async do while(data = socket.gets) json = JSON.parse(data) @@ -115,6 +119,8 @@ module W3DHubLauncher # puts "Timed out waiting for: #{echo_requests.values.select { |v| v[:replied] == false }.map { |v| v[:address] }.join(', ')}" end + broadcast(:game_server_pings, data: @host_pings) + sleep 5 end end @@ -123,6 +129,14 @@ module W3DHubLauncher socket&.close end + def broadcast(type, data:) + payload = { type: :eventbus, request_id: -1, data: { type: type, data: data } }.to_json + + @client&.write(payload) + @client&.write(RESPONSE_SEPARATOR) + @client&.flush + end + # Send request to server def request(query) # pp [:client_request, query] @@ -150,14 +164,18 @@ module W3DHubLauncher request = W3DHubLauncher::Worker::Request.requests.find { |r| r.request_id == json["request_id"] } # pp [json, request] - return unless request - - CyberarmEngine::Window.instance&.add_to_queue(proc { - request.handle_event( - json["status"], - CyberarmEngine::Result.new(data: json["data"], error: json["error"]) - ) - }) + if request.nil? && json["request_id"] && json["type"] == "eventbus" + CyberarmEngine::Window.instance&.add_to_queue(proc { + CyberarmEngine::EventBus.publish(json["data"]["type"], json["data"]["data"]) + }) + else + CyberarmEngine::Window.instance&.add_to_queue(proc { + request.handle_event( + json["status"], + CyberarmEngine::Result.new(data: json["data"], error: json["error"]) + ) + }) + end rescue JSON::ParserError => e puts "This should never happen!?!?!" diff --git a/lib/worker/api/game_server.rb b/lib/worker/api/game_server.rb index 7c93810..fb75762 100644 --- a/lib/worker/api/game_server.rb +++ b/lib/worker/api/game_server.rb @@ -3,6 +3,8 @@ module W3DHubLauncher class Api # Designed to work with cyberarm's Game Server Hub service data, may work with W3D Hub's service with degraded metadata. class GameServer + BAD_OR_UNKNOWN_PING = 1_000_000 + attr_reader :id, :game, :channel, :address, :port, :region, :name, :password, :current_map, :player_count, :max_players, :match_start_time, :estimated_end_time, :match_remaining_time, @@ -55,6 +57,35 @@ module W3DHubLauncher def password? @password end + + def ping + MemCache.dig(:game_server_pings, @address) || BAD_OR_UNKNOWN_PING + end + + def ping_score_ratio + # under 50 is best, over 200 is worst + case ping + when 0..49 + return 1.0 + when 50..200 + 1.0 - (ping / 200.0) + 0.1 + else + return 0.1 + end + end + + def ping_score_color + case ping + when 0..49 # gentle green + 0xff_26a269 + when 50..149 # rich orange + 0xff_e5a50a + when 150..200 # dark red + 0xff_a51d2d + else # dark gray + 0xff_3d3846 + end + end end class Team