forked from xiangwang25/whale-town-front-v2
187 lines
6.2 KiB
GDScript
187 lines
6.2 KiB
GDScript
class_name NetworkConfig
|
|
|
|
# ============================================================================
|
|
# NetworkConfig.gd - 前端网络环境配置
|
|
# ============================================================================
|
|
# 统一解析本地调试/线上环境的 HTTP 和 WebSocket 地址。
|
|
# 优先级:
|
|
# 1) 环境变量
|
|
# 2) Config/game_config.json 中 active_profile 对应的 profiles 配置
|
|
# 3) network 下的兼容字段
|
|
# 4) 线上默认值
|
|
# ============================================================================
|
|
|
|
const CONFIG_PATHS: Array[String] = [
|
|
"res://Config/game_config.json",
|
|
"res://config/game_config.json"
|
|
]
|
|
|
|
const DEFAULT_PROFILE: String = "production"
|
|
const DEFAULT_API_BASE_URL: String = "https://whaletownend.xinghangee.icu"
|
|
const DEFAULT_WS_URL: String = "wss://whaletownend.xinghangee.icu/game"
|
|
|
|
const API_BASE_URL_ENV_KEY: String = "WHALETOWN_API_BASE_URL"
|
|
const CHAT_WS_URL_ENV_KEY: String = "WHALETOWN_CHAT_WS_URL"
|
|
const LOCATION_WS_URL_ENV_KEY: String = "WHALETOWN_LOCATION_WS_URL"
|
|
const GAME_WS_URL_ENV_KEY: String = "WHALETOWN_GAME_WS_URL"
|
|
const PROFILE_ENV_KEY: String = "WHALETOWN_NETWORK_PROFILE"
|
|
|
|
static func get_api_base_url() -> String:
|
|
var query_url: String = _get_browser_url_override("api_base_url", ["http://", "https://"])
|
|
if not query_url.is_empty():
|
|
return _trim_trailing_slash(query_url)
|
|
|
|
var env_url: String = OS.get_environment(API_BASE_URL_ENV_KEY).strip_edges()
|
|
if not env_url.is_empty():
|
|
return _trim_trailing_slash(env_url)
|
|
|
|
var network_config := _get_active_network_config()
|
|
var url: String = str(network_config.get("api_base_url", "")).strip_edges()
|
|
if not url.is_empty():
|
|
return _trim_trailing_slash(url)
|
|
|
|
return DEFAULT_API_BASE_URL
|
|
|
|
static func get_chat_ws_url() -> String:
|
|
var query_url: String = _get_browser_url_override("chat_ws_url", ["ws://", "wss://"])
|
|
if not query_url.is_empty():
|
|
return query_url
|
|
|
|
var env_url: String = OS.get_environment(CHAT_WS_URL_ENV_KEY).strip_edges()
|
|
if not env_url.is_empty():
|
|
return env_url
|
|
|
|
var network_config := _get_active_network_config()
|
|
var url: String = str(network_config.get("chat_ws_url", network_config.get("game_ws_url", ""))).strip_edges()
|
|
if not url.is_empty():
|
|
return url
|
|
|
|
return DEFAULT_WS_URL
|
|
|
|
static func get_location_ws_url() -> String:
|
|
var query_url: String = _get_browser_url_override("location_ws_url", ["ws://", "wss://"])
|
|
if not query_url.is_empty():
|
|
return query_url
|
|
|
|
var game_query_url: String = _get_browser_url_override("game_ws_url", ["ws://", "wss://"])
|
|
if not game_query_url.is_empty():
|
|
return game_query_url
|
|
|
|
var env_url: String = OS.get_environment(LOCATION_WS_URL_ENV_KEY).strip_edges()
|
|
if not env_url.is_empty():
|
|
return env_url
|
|
|
|
var game_env_url: String = OS.get_environment(GAME_WS_URL_ENV_KEY).strip_edges()
|
|
if not game_env_url.is_empty():
|
|
return game_env_url
|
|
|
|
var network_config := _get_active_network_config()
|
|
var url: String = str(network_config.get("location_ws_url", network_config.get("game_ws_url", ""))).strip_edges()
|
|
if not url.is_empty():
|
|
return url
|
|
|
|
return DEFAULT_WS_URL
|
|
|
|
static func get_active_profile() -> String:
|
|
var query_profile: String = _get_browser_query_value("network_profile")
|
|
if not query_profile.is_empty():
|
|
return query_profile
|
|
|
|
var short_query_profile: String = _get_browser_query_value("profile")
|
|
if not short_query_profile.is_empty():
|
|
return short_query_profile
|
|
|
|
var env_profile: String = OS.get_environment(PROFILE_ENV_KEY).strip_edges()
|
|
if not env_profile.is_empty():
|
|
return env_profile
|
|
|
|
var root := _load_config()
|
|
var network_variant: Variant = root.get("network", {})
|
|
if network_variant is Dictionary:
|
|
var network_config: Dictionary = network_variant
|
|
var active_profile: String = str(network_config.get("active_profile", "")).strip_edges()
|
|
if not active_profile.is_empty():
|
|
return active_profile
|
|
|
|
return DEFAULT_PROFILE
|
|
|
|
static func is_local_debug() -> bool:
|
|
return get_active_profile() == "local"
|
|
|
|
static func get_summary() -> Dictionary:
|
|
return {
|
|
"profile": get_active_profile(),
|
|
"api_base_url": get_api_base_url(),
|
|
"chat_ws_url": get_chat_ws_url(),
|
|
"location_ws_url": get_location_ws_url()
|
|
}
|
|
|
|
static func _get_active_network_config() -> Dictionary:
|
|
var root := _load_config()
|
|
var network_variant: Variant = root.get("network", {})
|
|
if not (network_variant is Dictionary):
|
|
return {}
|
|
|
|
var network_config: Dictionary = network_variant
|
|
var active_profile := get_active_profile()
|
|
var profiles_variant: Variant = network_config.get("profiles", {})
|
|
if profiles_variant is Dictionary:
|
|
var profiles: Dictionary = profiles_variant
|
|
var profile_variant: Variant = profiles.get(active_profile, {})
|
|
if profile_variant is Dictionary:
|
|
return profile_variant
|
|
|
|
return network_config
|
|
|
|
static func _load_config() -> Dictionary:
|
|
for config_path in CONFIG_PATHS:
|
|
if not FileAccess.file_exists(config_path):
|
|
continue
|
|
|
|
var content: String = FileAccess.get_file_as_string(config_path)
|
|
if content.is_empty():
|
|
continue
|
|
|
|
var json := JSON.new()
|
|
if json.parse(content) != OK:
|
|
push_warning("NetworkConfig: 读取配置失败 %s - %s" % [config_path, json.get_error_message()])
|
|
continue
|
|
|
|
var data_variant: Variant = json.data
|
|
if data_variant is Dictionary:
|
|
return data_variant
|
|
|
|
return {}
|
|
|
|
static func _get_browser_query_value(key: String) -> String:
|
|
if OS.get_name() != "Web" or not OS.is_debug_build():
|
|
return ""
|
|
|
|
if not Engine.has_singleton("JavaScriptBridge"):
|
|
return ""
|
|
|
|
var js_bridge: Object = Engine.get_singleton("JavaScriptBridge")
|
|
if js_bridge == null:
|
|
return ""
|
|
|
|
var script := "new URLSearchParams(window.location.search).get('%s') || ''" % key
|
|
var value: Variant = js_bridge.eval(script, true)
|
|
return str(value).strip_edges()
|
|
|
|
static func _get_browser_url_override(key: String, allowed_schemes: Array[String]) -> String:
|
|
var value := _get_browser_query_value(key)
|
|
if value.is_empty():
|
|
return ""
|
|
var normalized := value.to_lower()
|
|
for scheme in allowed_schemes:
|
|
if normalized.begins_with(scheme):
|
|
return value
|
|
push_warning("NetworkConfig: 忽略无效的浏览器网络地址覆盖 %s" % key)
|
|
return ""
|
|
|
|
static func _trim_trailing_slash(url: String) -> String:
|
|
var trimmed := url.strip_edges()
|
|
while trimmed.ends_with("/") and trimmed.length() > 1:
|
|
trimmed = trimmed.substr(0, trimmed.length() - 1)
|
|
return trimmed
|