diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f7c7b..70ae0ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## [5.3.1] 2024-06-15 +### Added +- Uninstall routine: invoke via dzgui.sh -u or dzgui.sh --uninstall and choose from full or partial uninstall + +## [5.3.0] 2024-06-15 +### Added +- Server browser tables now display the number of players in queue (for full servers) +- Warning dialog if the user's API key returned no servers, and a global API cooldown dialog (60 seconds) +### Fixed +- Removing servers from My Servers via the right-click context menu was not actually removing the server and drawing an empty dialog +- Resolved an issue where, when Steam was not installed in a standard location and the user was prompted to let DZGUI auto-discover the correct path, this information was not retained correctly + ## [5.2.4] 2024-05-29 ### Fixed - Resolved an issue that could cause an old path to a prior DayZ installation to be reinserted in the config file if the Steam client did not synch the new path internally. DZGUI would try to ask the user to re-run first-time setup and update the path, but the old path would still be used. diff --git a/docs/dzgui.adoc b/docs/dzgui.adoc index d14e606..4b4b41c 100644 --- a/docs/dzgui.adoc +++ b/docs/dzgui.adoc @@ -107,7 +107,7 @@ Enable a Proton version ≥ `6.8` (or use Proton Experimental) in the `Compatibi ==== BattleMetrics API key (optional) -This key is optional. Using this key in conjunction with the above allows you to also connect to and query servers by numerical ID instead of by IP. See <>. +This key is optional. Using this key in conjunction with the above allows you to also connect to and query servers by numerical ID instead of by IP. See < Add server by ID, Add server by ID>>. 1. Register for an API key at https://www.battlemetrics.com/account/register?after=%2Fdevelopers[BattleMetrics] (free). 2. From the **Personal Access Tokens** area, Select **New Token**. @@ -297,6 +297,14 @@ LC_ALL=de_DE.UTF-8 ./dzgui.sh If you intend to use this frequently, you could wrap the above in a script or alias. +== Uninstallation + +To uninstall DZGUI and its associated files, invoke `./dzgui.sh` with the `-u` or `--uninstall` flag. + +Follow the prompts to choose from full uninstall (removes the application and all user-defined configuration files) or partial install (removes the application, but keeps user-defined configuration files). + +If you intend to reinstall DZGUI again, keeping your configuration files is recommended. + == Basic usage Select from among the <> below. @@ -340,7 +348,7 @@ Prints metadata for the servers saved in your servers list. Servers can be added For details on interacting with server browsing contexts, which are uniform across different menus, refer to <>. ==== Main menu > Quick connect to favorite server -Bypasses the server list and quick-connects to a single favorite server specified in advance using the <> option. +Bypasses the server list and quick-connects to a single favorite server specified in advance using the < Add (change) favorite server, Add (change) favorite server>> option. ==== Main menu > Recent servers This feature queries the history file for the last 10 servers connected to by any means @@ -365,7 +373,7 @@ Add a server to your saved servers list by IP. Provide the IP and query port in `:` format. -Servers you add will be saved and listed when using the <> option. +Servers you add will be saved and listed when using the <
My saved servers, My saved servers>> option. ==== Manage > Add server by ID Requires a <>. Use the https://www.battlemetrics.com/servers/dayz[BattleMetrics site] to find servers of interest (proximity, player count, rules, etc.) @@ -373,7 +381,7 @@ Requires a <>. Use the https://www.battlemetri Each server has a unique ID. This is the string of numbers at the end of the URL. Copy these IDs. For example, in the URL https://www.battlemetrics.com/servers/dayz/8039514, the ID is `8039514`. -Servers you add will be saved and listed when using the <> option. +Servers you add will be saved and listed when using the <
My saved servers, My saved servers>> option. ==== Manage > Add (change) favorite server Prompts you to add/change a favorite server (limit one). The name of the server will be updated in the footer of the app when focused on the <
Quick connect to favorite server, Quick connect to favorite server>> option in the <
> context. If a favorite server is already enabled, this option switches to "Change favorite server." @@ -387,35 +395,35 @@ Prints a scrollable dialog containing all locally-installed mods and their corre If you right-click on an entry in the list, you have the option of opening the Workshop page for the mod in Steam or deleting the local mod. -===== Options > Toggle release branch +==== Options > Toggle release branch Used to toggle the branch to fetch DZGUI from between `stable` and `testing`. The app ships with the stable branch enabled, with the testing branch being used to elaborate various experimental features. -===== Options > Toggle mod install mode +==== Options > Toggle mod install mode This feature is experimental. It attempts to queue the mods requested for download automatically, rather than prompting the user to subscribe to each one. [NOTE] When using auto mod installation, DZGUI will track the latest version of your installed mods and periodically synchronize their signatures next time you attempt to connect to a server. This means that if you satisfy the mods needed for a server, but updates to other mods you already have are found, an update will be triggered until all of your local mods are refreshed. Provided you tend to keep auto mod install on, these updates should be atomic and ensure that mods are always up to date. -===== Options > Toggle Steam/Flatpak +==== Options > Toggle Steam/Flatpak This feature should be used if there are concurrent installations of Steam on the local system. Toggle between using Steam or Flatpak Steam to launch DayZ. -===== Options > Change player name +==== Options > Change player name Used to change the in-game player name that is broadcast when on servers. -===== Options > Change Steam API key +==== Options > Change Steam API key Used to change or update the Steam API key; can be used if the old key needs to be revoked and updated with a new one. -===== Options > Change Battlemetrics API key +==== Options > Change Battlemetrics API key Identical to the option above, only for Battlemetrics. -===== Options > Force update local mods +==== Options > Force update local mods Attempts to update the signatures of all local mods and synchronize them with the latest versions available on Steam Workshop. This option should be used when < Toggle mod install mode, Toggle mod install mode>> is set to AUTO. This can be used in the event of mod corruption or linkage errors. -===== Output system info to log file +==== Output system info to log file Writes a list of your current settings and system configuration to a local file that can be pasted into bug reports. This process may take some time. The file is written to `$HOME/.local/state/dzgui/logs/DZGUI_SYSTEM.log` @@ -463,7 +471,7 @@ Due to size constraints, this button is not currently available on Steam Deck. [%autowidth] All server browser contexts (<
My saved servers, My saved servers>>, <
Server browser, Server browser>>, <
Recent servers, Recent servers>>) expose the following filters on the right-hand side. These options can be combined. -The table lists servers in columnar fashion according by: +The table lists servers in columnar fashion according to: - **Name**: the server name and the menu context you are currently on - **Map**: the map name @@ -471,6 +479,7 @@ The table lists servers in columnar fashion according by: - **Gametime**: in-game time on the 24-hour clock - **Players**: total players currently in-game - **Maximum**: total players the server supports +- **Queue**: total players in the waiting queue (for full servers) - **Address**: the address in IP:Port format - **Qport**: the query port of the listening server @@ -549,7 +558,7 @@ This depends on server operators checking their mods for integrity. A mod is corrupted or the issue lies with the server. Replace the mods in question and reconnect. .The game is slow or prone to crashing -DayZ does not manipulate the game itself and does not contribute to/degrade its performance. +DZGUI does not manipulate the game itself and does not contribute to/degrade its performance. If you are experiencing performance degradation, it can be caused by too many mods installed or by a server-side problem (underpowered server, misconfiguration, etc.) Contact the server administrator for assistance. diff --git a/docs/dzgui_dark.adoc b/docs/dzgui_dark.adoc index 3b4f229..41316ee 100644 --- a/docs/dzgui_dark.adoc +++ b/docs/dzgui_dark.adoc @@ -107,7 +107,7 @@ Enable a Proton version ≥ `6.8` (or use Proton Experimental) in the `Compatibi ==== BattleMetrics API key (optional) -This key is optional. Using this key in conjunction with the above allows you to also connect to and query servers by numerical ID instead of by IP. See <>. +This key is optional. Using this key in conjunction with the above allows you to also connect to and query servers by numerical ID instead of by IP. See < Add server by ID, Add server by ID>>. 1. Register for an API key at https://www.battlemetrics.com/account/register?after=%2Fdevelopers[BattleMetrics] (free). 2. From the **Personal Access Tokens** area, Select **New Token**. @@ -297,6 +297,14 @@ LC_ALL=de_DE.UTF-8 ./dzgui.sh If you intend to use this frequently, you could wrap the above in a script or alias. +== Uninstallation + +To uninstall DZGUI and its associated files, invoke `./dzgui.sh` with the `-u` or `--uninstall` flag. + +Follow the prompts to choose from full uninstall (removes the application and all user-defined configuration files) or partial install (removes the application, but keeps user-defined configuration files). + +If you intend to reinstall DZGUI again, keeping your configuration files is recommended. + == Basic usage Select from among the <> below. @@ -340,7 +348,7 @@ Prints metadata for the servers saved in your servers list. Servers can be added For details on interacting with server browsing contexts, which are uniform across different menus, refer to <>. ==== Main menu > Quick connect to favorite server -Bypasses the server list and quick-connects to a single favorite server specified in advance using the <> option. +Bypasses the server list and quick-connects to a single favorite server specified in advance using the < Add (change) favorite server, Add (change) favorite server>> option. ==== Main menu > Recent servers This feature queries the history file for the last 10 servers connected to by any means @@ -365,7 +373,7 @@ Add a server to your saved servers list by IP. Provide the IP and query port in `:` format. -Servers you add will be saved and listed when using the <> option. +Servers you add will be saved and listed when using the <
My saved servers, My saved servers>> option. ==== Manage > Add server by ID Requires a <>. Use the https://www.battlemetrics.com/servers/dayz[BattleMetrics site] to find servers of interest (proximity, player count, rules, etc.) @@ -373,7 +381,7 @@ Requires a <>. Use the https://www.battlemetri Each server has a unique ID. This is the string of numbers at the end of the URL. Copy these IDs. For example, in the URL https://www.battlemetrics.com/servers/dayz/8039514, the ID is `8039514`. -Servers you add will be saved and listed when using the <> option. +Servers you add will be saved and listed when using the <
My saved servers, My saved servers>> option. ==== Manage > Add (change) favorite server Prompts you to add/change a favorite server (limit one). The name of the server will be updated in the footer of the app when focused on the <
Quick connect to favorite server, Quick connect to favorite server>> option in the <
> context. If a favorite server is already enabled, this option switches to "Change favorite server." @@ -387,35 +395,35 @@ Prints a scrollable dialog containing all locally-installed mods and their corre If you right-click on an entry in the list, you have the option of opening the Workshop page for the mod in Steam or deleting the local mod. -===== Options > Toggle release branch +==== Options > Toggle release branch Used to toggle the branch to fetch DZGUI from between `stable` and `testing`. The app ships with the stable branch enabled, with the testing branch being used to elaborate various experimental features. -===== Options > Toggle mod install mode +==== Options > Toggle mod install mode This feature is experimental. It attempts to queue the mods requested for download automatically, rather than prompting the user to subscribe to each one. [NOTE] When using auto mod installation, DZGUI will track the latest version of your installed mods and periodically synchronize their signatures next time you attempt to connect to a server. This means that if you satisfy the mods needed for a server, but updates to other mods you already have are found, an update will be triggered until all of your local mods are refreshed. Provided you tend to keep auto mod install on, these updates should be atomic and ensure that mods are always up to date. -===== Options > Toggle Steam/Flatpak +==== Options > Toggle Steam/Flatpak This feature should be used if there are concurrent installations of Steam on the local system. Toggle between using Steam or Flatpak Steam to launch DayZ. -===== Options > Change player name +==== Options > Change player name Used to change the in-game player name that is broadcast when on servers. -===== Options > Change Steam API key +==== Options > Change Steam API key Used to change or update the Steam API key; can be used if the old key needs to be revoked and updated with a new one. -===== Options > Change Battlemetrics API key +==== Options > Change Battlemetrics API key Identical to the option above, only for Battlemetrics. -===== Options > Force update local mods +==== Options > Force update local mods Attempts to update the signatures of all local mods and synchronize them with the latest versions available on Steam Workshop. This option should be used when < Toggle mod install mode, Toggle mod install mode>> is set to AUTO. This can be used in the event of mod corruption or linkage errors. -===== Output system info to log file +==== Output system info to log file Writes a list of your current settings and system configuration to a local file that can be pasted into bug reports. This process may take some time. The file is written to `$HOME/.local/state/dzgui/logs/DZGUI_SYSTEM.log` @@ -463,7 +471,7 @@ Due to size constraints, this button is not currently available on Steam Deck. [%autowidth] All server browser contexts (<
My saved servers, My saved servers>>, <
Server browser, Server browser>>, <
Recent servers, Recent servers>>) expose the following filters on the right-hand side. These options can be combined. -The table lists servers in columnar fashion according by: +The table lists servers in columnar fashion according to: - **Name**: the server name and the menu context you are currently on - **Map**: the map name @@ -471,6 +479,7 @@ The table lists servers in columnar fashion according by: - **Gametime**: in-game time on the 24-hour clock - **Players**: total players currently in-game - **Maximum**: total players the server supports +- **Queue**: total players in the waiting queue (for full servers) - **Address**: the address in IP:Port format - **Qport**: the query port of the listening server @@ -549,7 +558,7 @@ This depends on server operators checking their mods for integrity. A mod is corrupted or the issue lies with the server. Replace the mods in question and reconnect. .The game is slow or prone to crashing -DayZ does not manipulate the game itself and does not contribute to/degrade its performance. +DZGUI does not manipulate the game itself and does not contribute to/degrade its performance. If you are experiencing performance degradation, it can be caused by too many mods installed or by a server-side problem (underpowered server, misconfiguration, etc.) Contact the server administrator for assistance. diff --git a/dzgui.sh b/dzgui.sh index d817cf0..99747d0 100755 --- a/dzgui.sh +++ b/dzgui.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -o pipefail -version=5.2.4 +version=5.3.1 #CONSTANTS aid=221100 @@ -35,6 +35,7 @@ prefix="dzg" history_file="$state_path/$prefix.history" versions_file="$state_path/$prefix.versions" lock_file="$state_path/$prefix.lock" +cols_file="$state_path/$prefix.cols.json" #CACHE FILES coords_file="$cache_path/$prefix.coords" @@ -237,6 +238,7 @@ watcher_deps(){ logger INFO "Found DZG Watcher dependencies" } format_version_url(){ + [[ -z "$branch" ]] && branch="stable" case "$branch" in "stable") version_url="$stable_url/dzgui.sh" @@ -530,13 +532,13 @@ fetch_dzq(){ logger INFO "Updated DZQ to sha '$sha'" } fetch_helpers_by_sum(){ - source "$config_file" + [[ -f "$config_file" ]] && source "$config_file" declare -A sums sums=( - ["ui.py"]="1e692d9c658aba4402c1c998263f6184" + ["ui.py"]="f14772424461ec438579dec567db0634" ["query_v2.py"]="1822bd1769ce7d7cb0d686a60f9fa197" ["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397" - ["funcs"]="47ba5f1b5da5d1e7f42a5a088b29ec9d" + ["funcs"]="37ae407ac397f6775f3a412e7adb7840" ) local author="aclist" local repo="dztui" @@ -610,7 +612,7 @@ test_steam_api(){ [[ -z $key ]] && return 1 local url="https://api.steampowered.com/IGameServersService/GetServerList/v1/?filter=\appid\221100&limit=10&key=$key" local code=$(curl -ILs "$url" | grep -E "^HTTP") - [[ $code =~ 403 ]] && echo 1 + [[ ! $code =~ 200 ]] && echo 1 [[ $code =~ 200 ]] && echo 0 } test_bm_api(){ @@ -626,10 +628,18 @@ test_bm_api(){ } find_default_path(){ _discover(){ - default_steam_path=$(find / -type d \( -path "/proc" -o -path "*/timeshift" -o -path \ - "/tmp" -o -path "/usr" -o -path "/boot" -o -path "/proc" -o -path "/root" \ - -o -path "/sys" -o -path "/etc" -o -path "/var" -o -path "/lost+found" \) -prune \ - -o -regex ".*/Steam/ubuntu12_32$" -print -quit 2>/dev/null | sed 's@/ubuntu12_32@@') + readarray -t paths < <(find / -type d \( -path "/proc" -o -path "*/timeshift" -o -path \ + "/tmp" -o -path "/usr" -o -path "/boot" -o -path "/proc" -o -path "/root" \ + -o -path "/sys" -o -path "/etc" -o -path "/var" -o -path "/lost+found" \) -prune \ + -o -regex ".*Steam/config/libraryfolders.vdf$" -print 2>/dev/null | sed 's@/config/libraryfolders.vdf@@') + + if [[ "${#paths[@]}" -gt 1 ]]; then + echo "100" + default_steam_path=$(printf "%s\n" "${paths[@]}" | $steamsafe_zenity --list --column="paths" --hide-header --text="Found multiple valid Steam paths. Select your default Steam installation." --title="DZGUI") + [[ -z "$default_steam_path" ]] && exit 1 + else + default_steam_path="${paths[0]}" + fi } if [[ $is_steam_deck -gt 0 ]]; then default_steam_path="$HOME/.local/share/Steam" @@ -653,15 +663,15 @@ find_default_path(){ done local msg="Let DZGUI auto-discover Steam path (accurate, slower)\nSelect the Steam path manually (less accurate, faster)" - echo -e "$msg" | $steamsafe_zenity --list \ + local res=$(echo -e "$msg" | $steamsafe_zenity --list \ --column="Choice" \ --title="DZGUI" \ --hide-header \ --text="Steam is not installed in a standard location." \ - $sd_res + $sd_res) case "$res" in - *auto*) _discover ;; + *auto*) _discover > >(pdialog "Scanning paths") ;; *manual*) zenity --info --text="\nSelect the top-level entry point to the location where Steam (not DayZ)\nis installed and before entering the \"steamapps\" path.\n\nE.g., if Steam is installed at:\n\"/media/mydrive/Steam\"\n\nCorrect:\n- \"/media/mydrive/Steam\"\n\nIncorrect:\n- \"/media/mydrive/Steam/steamapps/common/DayZ\"\n- \"/media/mydrive/\"" --width=500 && file_picker ;; @@ -806,6 +816,13 @@ test_connection(){ raise_error_and_quit "No connection could be established to the remote server (steampowered.com)." fi } +legacy_cols(){ + [[ ! -f $cols_file ]] && return + local has=$(< "$cols_file" jq '.cols|has("Queue")') + [[ $has == "true" ]] && return + < $cols_file jq '.cols += { "Queue": 120 }' > $cols_file.new && + mv $cols_file.new $cols_file +} initial_setup(){ setup_dirs setup_state_files @@ -820,6 +837,7 @@ initial_setup(){ source "$config_file" lock legacy_vars + legacy_cols check_version check_map_count steam_deps @@ -830,9 +848,56 @@ initial_setup(){ is_dzg_downloading print_config_vals } +uninstall(){ + _full(){ + for i in "$config_path" "$state_path" "$cache_path" "$share_path"; do + echo "Deleting the path '$i'" + rm -rf "$i" + done + } + _partial(){ + for i in "$cache_path" "$share_path"; do + echo "Deleting the path '$i'" + rm -rf "$i" + done + } + local choice=$($steamsafe_zenity \ + --list \ + --radiolist \ + --column="a" \ + --column="b" \ + --hide-header \ + --text="Choose an uninstall routine below." \ + TRUE "Keep user config files" \ + FALSE "Delete all DZGUI files" \ + --title="DZGUI" + ) + + case "$choice" in + "Keep user config files") + _partial + ;; + "Delete all DZGUI files") + _full + ;; + "") + echo "User aborted uninstall process" + exit 1 + ;; + esac + local self="$(realpath "$0")" + echo "Deleting '$self'" + rm "$self" + echo "Uninstall routine complete" +} main(){ local zenv=$(zenity --version 2>/dev/null) [[ -z $zenv ]] && { echo "Requires zenity <= 3.44.1"; exit 1; } + if [[ $1 == "--uninstall" ]] || [[ $1 == "-u" ]]; then + uninstall && + exit 0 + fi + set_im_module printf "Initializing setup...\n" @@ -841,6 +906,6 @@ main(){ printf "All OK. Kicking off UI...\n" python3 "$ui_helper" "--init-ui" "$version" "$is_steam_deck" } -main +main "$@" #TODO: tech debt: cruddy handling for steam forking [[ $? -eq 1 ]] && pkill -f dzgui.sh diff --git a/helpers/funcs b/helpers/funcs index d7f1ac0..8146bd7 100755 --- a/helpers/funcs +++ b/helpers/funcs @@ -43,6 +43,7 @@ _cache_history="$cache_dir/$prefix.history" _cache_launch="$cache_dir/$prefix.launch_mods" _cache_address="$cache_dir/$prefix.launch_address" _cache_coords="$cache_path/$prefix.coords" +_cache_cooldown="$cache_path/$prefix.cooldown" #XDG freedesktop_path="$HOME/.local/share/applications" @@ -107,7 +108,9 @@ declare -A funcs=( ["dump_servers"]="dump_servers" ["get_unique_maps"]="get_unique_maps" ["get_dist"]="get_dist" +["test_cooldown"]="test_cooldown" ["query_config"]="query_config" +["start_cooldown"]="start_cooldown" ["list_mods"]="list_mods" ["delete"]="delete_local_mod" ["show_server_modlist"]="show_server_modlist" @@ -117,7 +120,7 @@ declare -A funcs=( ["gen_log"]="generate_log" ["open_workshop_page"]="open_workshop_page" ["Add to my servers"]="update_favs_from_table" -["Remove from favorites"]="update_favs_from_table" +["Remove from my servers"]="update_favs_from_table" ["Remove from history"]="remove_from_history" ["force_update"]="force_update" ["Handshake"]="final_handshake" @@ -132,7 +135,8 @@ get_player_count(){ res=$(a2s $ip $qport info) [[ ! $? -eq 0 ]] && return 1 local players="$(<<< $res jq -r '.[].players')" - printf "%s" "$players" + local queue="$(<<< $res jq -r '.[].gametype|split("lqs")[1]|split(",")[0]')" + printf "%s\n%s" "$players" "$queue" } validate_and_connect(){ @@ -252,6 +256,10 @@ connect_by_id(){ fi #res contains modlist } +start_cooldown(){ + logger WARN "API response empty. Started 60s cooldown at $(date +%s)" + date +%s > $_cache_cooldown +} initialize_remote_servers(){ local file="$_cache_servers" [[ -f $file ]] && rm "$file" @@ -513,6 +521,7 @@ parse_server_json(){ "\(if .gametype == null then "null" else (.gametype as $time|$time|test("[0-9]{2}:[0-9]{2}$") as $match|(if $match == true then ($time|scan("[0-9]{2}:[0-9]{2}$")) else "XXXX" end)) end)␞" + "\(.players)␞" + "\(.max_players)␞" + + "\(if .gametype == null then "0" else .gametype|split("lqs")[1]|split(",")[0] end)␞" + "\(.addr|split(":")[0]):\(if .gameport == null then "XXXX" else .gameport end)␞" + "\(.addr|split(":")[1])" ' | sort -k1 @@ -526,6 +535,19 @@ delete_local_mod(){ #SC2115 rm -rf "${workshop_dir:?}/$dir" && unlink "$game_dir/$symlink" || return 1 } +test_cooldown(){ + [[ ! -f $_cache_cooldown ]] && return 0 + local old_time=$(< $_cache_cooldown) + local cur_time=$(date +%s) + local delta=$(($cur_time - $old_time)) + local suffix="seconds" + if [[ $delta -lt 60 ]]; then + local remains=$((60 - $delta)) + [[ $remains -eq 1 ]] && suffix="second" + printf "Global API cooldown in effect. Please wait %s %s." "$remains" "$suffix" + exit 1 + fi +} dump_servers(){ local context="$1" local subcontext="$2" diff --git a/helpers/ui.py b/helpers/ui.py index 519278a..b830ce8 100644 --- a/helpers/ui.py +++ b/helpers/ui.py @@ -36,12 +36,12 @@ checks = list() map_store = Gtk.ListStore(str) row_store = Gtk.ListStore(str) modlist_store = Gtk.ListStore(str, str, str) -# Name, Symlink, ID, Size +#cf. mod_cols mod_store = Gtk.ListStore(str, str, str, float) -# Timestamp, Flag, Trace, Message +#cf. log_cols log_store = Gtk.ListStore(str, str, str, str) -# Name, Map, Perspective, Gametime, Players, Max, IP, Qport -server_store = Gtk.ListStore(str, str, str, str, int, int, str, int) +#cf. browser_cols +server_store = Gtk.ListStore(str, str, str, str, int, int, int, str, int) default_tooltip = "Select a row to see its detailed description" server_tooltip = [None, None] @@ -69,6 +69,7 @@ browser_cols = [ "Gametime", "Players", "Maximum", + "Queue", "IP", "Qport", ] @@ -230,7 +231,7 @@ def parse_server_rows(data): reader = csv.reader(lines, delimiter=delimiter) hits = len(lines) try: - rows = [[row[0], row[1], row[2], row[3], int(row[4]), int(row[5]), row[6], int(row[7])] for row in reader if row] + rows = [[row[0], row[1], row[2], row[3], int(row[4]), int(row[5]), int(row[6]), row[7], int(row[8])] for row in reader if row] except IndexError: return 1 for row in rows: @@ -690,7 +691,7 @@ class TreeView(Gtk.TreeView): match context_menu_label: case "Add to my servers" | "Remove from my servers": - record = "%s:%s" %(self.get_column_at_index(6), self.get_column_at_index(7)) + record = "%s:%s" %(self.get_column_at_index(7), self.get_column_at_index(8)) proc = call_out(parent, context_menu_label, record) if context == "Name (My saved servers)": iter = self.get_current_iter() @@ -698,21 +699,21 @@ class TreeView(Gtk.TreeView): msg = proc.stdout res = spawn_dialog(parent, msg, "NOTIFY") case "Remove from history": - record = "%s:%s" %(self.get_column_at_index(6), self.get_column_at_index(7)) + record = "%s:%s" %(self.get_column_at_index(7), self.get_column_at_index(8)) call_out(parent, context_menu_label, record) iter = self.get_current_iter() server_store.remove(iter) case "Copy IP to clipboard": self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) - addr = self.get_column_at_index(6) - qport = self.get_column_at_index(7) + addr = self.get_column_at_index(7) + qport = self.get_column_at_index(8) ip = addr.split(':')[0] record = "%s:%s" %(ip, qport) self.clipboard.set_text(record, -1) case "Refresh player count": self.refresh_player_count() case "Show server-side mods": - record = "%s:%s" %(self.get_column_at_index(6), self.get_column_at_index(7)) + record = "%s:%s" %(self.get_column_at_index(7), self.get_column_at_index(8)) dialog = ModDialog(parent, "Enter/double click a row to open in Steam Workshop. ESC exits this dialog", "Modlist", record) modlist_store.clear() case "Delete mod": @@ -765,7 +766,7 @@ class TreeView(Gtk.TreeView): for item in items: if subcontext == "Server browser" and item == "Add to my servers": - record = "%s:%s" %(self.get_column_at_index(6), self.get_column_at_index(7)) + record = "%s:%s" %(self.get_column_at_index(7), self.get_column_at_index(8)) proc = call_out(widget, "is_in_favs", record) if proc.returncode == 0: item = "Remove from my servers" @@ -824,7 +825,7 @@ class TreeView(Gtk.TreeView): self.current_proc.terminate() if "Name" in context: - addr = self.get_column_at_index(6) + addr = self.get_column_at_index(7) if addr is None: return if addr in cache: @@ -912,7 +913,11 @@ class TreeView(Gtk.TreeView): def _background_player_count(self): def _load(): - server_store[path][4] = int(data.stdout) + lines = data.stdout.splitlines() + #update players + server_store[path][4] = int(lines[0]) + #update queue + server_store[path][6] = int(lines[1]) wait_dialog.destroy() parent = self.get_outer_window() @@ -925,8 +930,8 @@ class TreeView(Gtk.TreeView): return path = pathlist[0] tree_iter = model.get_iter(path) - addr = server_store[path][6] - qport = server_store[path][7] + addr = server_store[path][7] + qport = server_store[path][8] ip = addr.split(':')[0] qport = str(qport) @@ -946,6 +951,13 @@ class TreeView(Gtk.TreeView): self.grab_focus() for column in self.get_columns(): column.connect("notify::width", self._on_col_width_changed) + if hits == 0: + call_out(self, "start_cooldown", "", "") + api_warn_msg = """\ + No servers returned. Possible network issue or API key on cooldown? + Return to the main menu, wait 60s, and try again. + If this issue persists, your API key may be defunct.""" + spawn_dialog(self.get_outer_window(), textwrap.dedent(api_warn_msg), "NOTIFY") grid = self.get_outer_grid() right_panel = grid.right_panel @@ -1137,8 +1149,8 @@ class TreeView(Gtk.TreeView): def _attempt_connection(self): transient_parent = self.get_outer_window() - addr = self.get_column_at_index(6) - qport = self.get_column_at_index(7) + addr = self.get_column_at_index(7) + qport = self.get_column_at_index(8) record = "%s:%s" %(addr, str(qport)) wait_dialog = GenericDialog(transient_parent, "Querying server and aligning mods", "WAIT") @@ -1166,6 +1178,10 @@ class TreeView(Gtk.TreeView): if chosen_row == "Server browser": reinit_checks() + cooldown = call_out(self, "test_cooldown", "", "") + if cooldown.returncode == 1: + spawn_dialog(self.get_outer_window(), cooldown.stdout, "NOTIFY") + return 1 else: for check in checks: if check.get_label() not in toggled_checks: