readability: extract magic constants, fix Go jargon
- goos/goarch -> os_name/arch_name (Go ecosystem jargon) - BUTLER_USER_AGENT now reads version from plugin.json at runtime - Added named constants: CONNECTION_TIMEOUT_ITERATIONS, CONNECTION_POLL_DELAY_MS, PERCENTAGE_SCALE, LAUNCH_WATCH_INTERVAL_SEC, UPDATE_CHECK_INTERVAL_SEC, BUTLERD_BOOT_MAX_ATTEMPTS, BUTLERD_BOOT_RETRY_DELAY_SEC, LAUNCH_WATCH_TIMEOUT_MS, EXECUTE_PERMISSION_BIT - Removed BYTES_PER_MB (inline 1024 * 1024 is clearer)
This commit is contained in:
parent
18f674c00b
commit
7ee08ac571
2 changed files with 38 additions and 18 deletions
|
|
@ -29,6 +29,9 @@ const butler_dir := "user://butler"
|
||||||
## survive plugin updates untouched.
|
## survive plugin updates untouched.
|
||||||
const games_dir := "user://butler/games"
|
const games_dir := "user://butler/games"
|
||||||
const CACHE_DIR := "itch"
|
const CACHE_DIR := "itch"
|
||||||
|
const CONNECTION_TIMEOUT_ITERATIONS := 50
|
||||||
|
const CONNECTION_POLL_DELAY_MS := 20
|
||||||
|
const PERCENTAGE_SCALE := 100
|
||||||
|
|
||||||
enum STATE {
|
enum STATE {
|
||||||
BOOT,
|
BOOT,
|
||||||
|
|
@ -101,7 +104,7 @@ func bootstrap() -> void:
|
||||||
"--keep-alive",
|
"--keep-alive",
|
||||||
"--dbpath", dbpath,
|
"--dbpath", dbpath,
|
||||||
"--address", "https://itch.io",
|
"--address", "https://itch.io",
|
||||||
"--user-agent", "OpenGamepadUI-itch/0.1.0",
|
"--user-agent", _get_user_agent(),
|
||||||
"--destiny-pid", str(OS.get_process_id()),
|
"--destiny-pid", str(OS.get_process_id()),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -138,21 +141,21 @@ func _migrate_butler(dest_dir: String) -> void:
|
||||||
## Downloads a butler binary for this platform from itch's broth distribution
|
## Downloads a butler binary for this platform from itch's broth distribution
|
||||||
## channel (the same one the official itch.io app uses to self-update).
|
## channel (the same one the official itch.io app uses to self-update).
|
||||||
func _install_butler() -> bool:
|
func _install_butler() -> bool:
|
||||||
var goos := "linux"
|
var os_name := "linux"
|
||||||
var goarch := "amd64"
|
var arch_name := "amd64"
|
||||||
if OS.get_name() == "Windows":
|
if OS.get_name() == "Windows":
|
||||||
goos = "windows"
|
os_name = "windows"
|
||||||
if OS.get_name() == "macOS":
|
if OS.get_name() == "macOS":
|
||||||
goos = "darwin"
|
os_name = "darwin"
|
||||||
# Engine.get_architecture_name() is only available on newer Godot 4.x
|
# Engine.get_architecture_name() is only available on newer Godot 4.x
|
||||||
# builds; guard it so this still works if OpenGamepadUI is running on an
|
# builds; guard it so this still works if OpenGamepadUI is running on an
|
||||||
# older engine version.
|
# older engine version.
|
||||||
if Engine.has_method("get_architecture_name"):
|
if Engine.has_method("get_architecture_name"):
|
||||||
var arch: String = Engine.get_architecture_name()
|
var arch: String = Engine.get_architecture_name()
|
||||||
if "arm64" in arch or "aarch64" in arch:
|
if "arm64" in arch or "aarch64" in arch:
|
||||||
goarch = "arm64"
|
arch_name = "arm64"
|
||||||
|
|
||||||
var platform_slug := goos + "-" + goarch
|
var platform_slug := os_name + "-" + arch_name
|
||||||
var latest_url := "/".join([broth_base, platform_slug, "LATEST"])
|
var latest_url := "/".join([broth_base, platform_slug, "LATEST"])
|
||||||
|
|
||||||
var http := HTTPRequest.new()
|
var http := HTTPRequest.new()
|
||||||
|
|
@ -204,6 +207,17 @@ func _install_butler() -> bool:
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
|
func _get_user_agent() -> String:
|
||||||
|
var version := "unknown"
|
||||||
|
var file := FileAccess.open("res://plugin.json", FileAccess.READ)
|
||||||
|
if file:
|
||||||
|
var json: Variant = JSON.parse_string(file.get_as_text())
|
||||||
|
file.close()
|
||||||
|
if json is Dictionary:
|
||||||
|
version = json.get("plugin.version", "unknown")
|
||||||
|
return "OpenGamepadUI-itch/" + version
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Wire protocol: spawn -> read handshake off stdout -> connect TCP -> auth
|
# Wire protocol: spawn -> read handshake off stdout -> connect TCP -> auth
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
@ -266,10 +280,10 @@ func _connect_and_authenticate(address: String, secret: String) -> void:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Wait for the connection to establish
|
# Wait for the connection to establish
|
||||||
var timeout := 50
|
var timeout := CONNECTION_TIMEOUT_ITERATIONS
|
||||||
while socket.get_status() == StreamPeerTCP.STATUS_CONNECTING and timeout > 0:
|
while socket.get_status() == StreamPeerTCP.STATUS_CONNECTING and timeout > 0:
|
||||||
socket.poll()
|
socket.poll()
|
||||||
OS.delay_msec(20)
|
OS.delay_msec(CONNECTION_POLL_DELAY_MS)
|
||||||
timeout -= 1
|
timeout -= 1
|
||||||
if socket.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
if socket.get_status() != StreamPeerTCP.STATUS_CONNECTED:
|
||||||
logger.error("Timed out connecting to butlerd")
|
logger.error("Timed out connecting to butlerd")
|
||||||
|
|
@ -790,8 +804,8 @@ func _install(game: Dictionary, cave_id: String, options: Dictionary) -> bool:
|
||||||
var progress: float = p.get("progress", 0.0)
|
var progress: float = p.get("progress", 0.0)
|
||||||
install_progressed.emit.call_deferred(
|
install_progressed.emit.call_deferred(
|
||||||
cave_id if cave_id != "" else str(game_id),
|
cave_id if cave_id != "" else str(game_id),
|
||||||
int(progress * 100),
|
int(progress * PERCENTAGE_SCALE),
|
||||||
100
|
PERCENTAGE_SCALE
|
||||||
)
|
)
|
||||||
rpc_notification.connect(on_notification)
|
rpc_notification.connect(on_notification)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,13 @@ extends Library
|
||||||
|
|
||||||
const ItchClient := preload("res://plugins/itch/core/itch_client.gd")
|
const ItchClient := preload("res://plugins/itch/core/itch_client.gd")
|
||||||
const _apps_cache_file: String = "apps.json"
|
const _apps_cache_file: String = "apps.json"
|
||||||
|
const LAUNCH_WATCH_INTERVAL_SEC := 2.0
|
||||||
|
const UPDATE_CHECK_INTERVAL_SEC := 600.0
|
||||||
|
const BUTLERD_BOOT_MAX_ATTEMPTS := 10
|
||||||
|
const BUTLERD_BOOT_RETRY_DELAY_SEC := 0.5
|
||||||
|
const LAUNCH_WATCH_TIMEOUT_MS := 5000
|
||||||
|
## 0o111 — execute bit set for any of owner/group/others.
|
||||||
|
const EXECUTE_PERMISSION_BIT := 73
|
||||||
|
|
||||||
var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
|
var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
|
||||||
|
|
||||||
|
|
@ -35,14 +42,14 @@ func _ready() -> void:
|
||||||
# instead of leaving the user stuck on a black in-game screen.
|
# instead of leaving the user stuck on a black in-game screen.
|
||||||
if load("res://core/global/launch_manager.tres") != null:
|
if load("res://core/global/launch_manager.tres") != null:
|
||||||
var watch_timer := Timer.new()
|
var watch_timer := Timer.new()
|
||||||
watch_timer.wait_time = 2.0
|
watch_timer.wait_time = LAUNCH_WATCH_INTERVAL_SEC
|
||||||
watch_timer.autostart = true
|
watch_timer.autostart = true
|
||||||
watch_timer.timeout.connect(_check_failed_launches)
|
watch_timer.timeout.connect(_check_failed_launches)
|
||||||
add_child(watch_timer)
|
add_child(watch_timer)
|
||||||
# Keep the has_update() flags fresh in the background (CheckUpdate hits the
|
# Keep the has_update() flags fresh in the background (CheckUpdate hits the
|
||||||
# itch.io API, so it must never run on the UI thread or per-library-load).
|
# itch.io API, so it must never run on the UI thread or per-library-load).
|
||||||
var update_timer := Timer.new()
|
var update_timer := Timer.new()
|
||||||
update_timer.wait_time = 600.0
|
update_timer.wait_time = UPDATE_CHECK_INTERVAL_SEC
|
||||||
update_timer.autostart = true
|
update_timer.autostart = true
|
||||||
update_timer.timeout.connect(_refresh_update_flags)
|
update_timer.timeout.connect(_refresh_update_flags)
|
||||||
add_child(update_timer)
|
add_child(update_timer)
|
||||||
|
|
@ -502,8 +509,8 @@ func _load_library(caching_flags: int = Cache.FLAGS.LOAD | Cache.FLAGS.SAVE) ->
|
||||||
cached_installed = true
|
cached_installed = true
|
||||||
break
|
break
|
||||||
var attempts := 0
|
var attempts := 0
|
||||||
while cached_installed and attempts < 10 and (caves == null or (caves.is_empty() and itch.state != ItchClient.STATE.CONNECTED)):
|
while cached_installed and attempts < BUTLERD_BOOT_MAX_ATTEMPTS and (caves == null or (caves.is_empty() and itch.state != ItchClient.STATE.CONNECTED)):
|
||||||
await get_tree().create_timer(0.5).timeout
|
await get_tree().create_timer(BUTLERD_BOOT_RETRY_DELAY_SEC).timeout
|
||||||
caves = await itch.get_caves()
|
caves = await itch.get_caves()
|
||||||
attempts += 1
|
attempts += 1
|
||||||
var caves_by_game_id := {}
|
var caves_by_game_id := {}
|
||||||
|
|
@ -792,8 +799,7 @@ func _candidate_is_game_binary(path: String) -> bool:
|
||||||
func _is_runnable_file(path: String) -> bool:
|
func _is_runnable_file(path: String) -> bool:
|
||||||
if path == "" or not FileAccess.file_exists(path):
|
if path == "" or not FileAccess.file_exists(path):
|
||||||
return false
|
return false
|
||||||
# 0o111 = execute bit set for any of owner/group/others.
|
return FileAccess.get_unix_permissions(path) & EXECUTE_PERMISSION_BIT != 0
|
||||||
return FileAccess.get_unix_permissions(path) & 73 != 0
|
|
||||||
|
|
||||||
|
|
||||||
## Looks up a runtime binary (love, java, ...). Checks the persistent runtime
|
## Looks up a runtime binary (love, java, ...). Checks the persistent runtime
|
||||||
|
|
@ -839,7 +845,7 @@ func _check_failed_launches() -> void:
|
||||||
continue
|
continue
|
||||||
if app.is_running():
|
if app.is_running():
|
||||||
continue
|
continue
|
||||||
if now - int(_launch_watch[app.pid]) < 5000:
|
if now - int(_launch_watch[app.pid]) < LAUNCH_WATCH_TIMEOUT_MS:
|
||||||
continue
|
continue
|
||||||
if app.pid in _diagnosed_pids:
|
if app.pid in _diagnosed_pids:
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue