1
0
Fork 0
mirror of https://github.com/aclist/dztui.git synced 2024-12-29 13:52:03 +01:00
dztui/dzgui.sh

1013 lines
31 KiB
Bash
Raw Normal View History

2023-05-16 00:14:56 +02:00
#!/usr/bin/env bash
2022-06-04 22:29:30 +02:00
set -o pipefail
2024-01-31 10:36:08 +01:00
2024-12-15 00:57:25 +01:00
version=5.6.0-beta.17
2022-08-14 04:03:27 +02:00
2024-01-31 10:36:08 +01:00
#CONSTANTS
2022-05-09 13:42:24 +02:00
aid=221100
game="dayz"
2024-01-31 10:36:08 +01:00
app_name="dzgui"
app_name_upper="DZGUI"
workshop="steam://url/CommunityFilePage/"
2022-05-22 21:20:34 +02:00
sd_res="--width=1280 --height=800"
2024-01-31 10:36:08 +01:00
steamsafe_zenity="/usr/bin/zenity"
zenity_flags=("--width=500" "--title=DZGUI")
declare -A deps
2024-08-27 23:52:01 +02:00
deps=([awk]="5.1.1" [curl]="7.80.0" [jq]="1.6" [tr]="9.0" [$steamsafe_zenity]="3.44.1")
2024-01-31 10:36:08 +01:00
#CONFIG
config_path="$HOME/.config/dztui"
config_file="$config_path/dztuirc"
#PATHS
state_path="$HOME/.local/state/$app_name"
cache_path="$HOME/.cache/$app_name"
share_path="$HOME/.local/share/$app_name"
script_path="$share_path/dzgui.sh"
helpers_path="$share_path/helpers"
#LOGS
log_path="$state_path/logs"
debug_log="$log_path/DZGUI_DEBUG.log"
#STATE FILES
prefix="dzg"
history_file="$state_path/$prefix.history"
versions_file="$state_path/$prefix.versions"
lock_file="$state_path/$prefix.lock"
2024-06-10 19:15:23 +02:00
cols_file="$state_path/$prefix.cols.json"
2024-01-31 10:36:08 +01:00
#CACHE FILES
coords_file="$cache_path/$prefix.coords"
#legacy paths
hist_file="$config_path/history"
version_file="$config_path/versions"
#XDG
2022-08-05 20:35:17 +02:00
freedesktop_path="$HOME/.local/share/applications"
2024-01-31 10:36:08 +01:00
#HELPERS
ui_helper="$helpers_path/ui.py"
2022-09-14 06:56:13 +02:00
geo_file="$helpers_path/ips.csv"
km_helper="$helpers_path/latlon"
sums_path="$helpers_path/sums.md5"
2024-01-31 10:36:08 +01:00
func_helper="$helpers_path/funcs"
2024-12-12 03:08:07 +01:00
#REMOTE
remote_host=gh
2024-01-31 10:36:08 +01:00
author="aclist"
2024-12-12 03:08:07 +01:00
repo="dztui"
url_prefix="https://raw.githubusercontent.com/$author/$repo"
2024-01-31 10:36:08 +01:00
stable_url="$url_prefix/dzgui"
testing_url="$url_prefix/testing"
2024-12-12 03:08:07 +01:00
releases_url="https://github.com/$author/$repo/releases/download/browser"
2022-09-14 06:56:13 +02:00
km_helper_url="$releases_url/latlon"
2024-01-31 10:36:08 +01:00
geo_file_url="$releases_url/ips.csv.gz"
2022-05-09 13:42:24 +02:00
2024-12-12 03:08:07 +01:00
2024-01-31 10:36:08 +01:00
set_im_module(){
2024-08-27 23:52:01 +02:00
#TODO: drop pending SteamOS changes
2024-01-31 10:36:08 +01:00
pgrep -a gamescope | grep -q "generate-drm-mode"
if [[ $? -eq 0 ]]; then
GTK_IM_MODULE=""
logger INFO "Detected Steam Deck (Game Mode), unsetting GTK_IM_MODULE"
else
return
fi
2022-07-24 15:20:06 +02:00
}
2024-01-31 10:36:08 +01:00
logger(){
local date="$(date "+%F %T,%3N")"
local tag="$1"
local string="$2"
local self="${BASH_SOURCE[0]}"
local caller="${FUNCNAME[1]}"
local line="${BASH_LINENO[0]}"
printf "%s␞%s␞%s::%s()::%s␞%s\n" "$date" "$tag" "$self" "$caller" "$line" "$string" >> "$debug_log"
}
setup_dirs(){
for dir in "$state_path" "$cache_path" "$share_path" "$helpers_path" "$freedesktop_path" "$config_path" "$log_path"; do
if [[ ! -d $dir ]]; then
mkdir -p "$dir"
fi
done
2022-07-24 15:20:06 +02:00
}
2024-01-31 10:36:08 +01:00
setup_state_files(){
if [[ -f "$debug_log" ]]; then
rm "$debug_log" && touch $debug_log
logger INFO "Initializing DZGUI version $version"
fi
if [[ -f "$version_file" ]]; then
mv "$version_file" "$versions_file" &&
logger INFO "Migrating legacy version file"
fi
# wipe cache files
local path="$cache_path"
if find "$path" -mindepth 1 -maxdepth 1 | read; then
for file in $path/*; do
rm "$file"
done
logger INFO "Wiped cache files"
2023-12-18 04:12:46 +01:00
fi
2022-06-12 06:44:30 +02:00
}
2024-01-31 10:36:08 +01:00
print_config_vals(){
local keys=(
"branch"
"name"
"fav_server"
"fav_label"
"auto_install"
"steam_path"
"default_steam_path"
"preferred_client"
)
for i in "${keys[@]}"; do
logger INFO "Read key '$i': '${!i}'"
done
if [[ ${#ip_list[@]} -lt 1 ]]; then
logger WARN "No IPs in saved server list"
fi
2022-05-09 13:42:24 +02:00
2022-10-09 04:07:07 +02:00
}
2024-01-31 10:36:08 +01:00
test_gobject(){
python3 -c "import gi"
if [[ ! $? -eq 0 ]]; then
logger CRITICAL "Missing PyGObject"
2024-04-01 10:11:19 +02:00
fdialog "Requires PyGObject (python-gobject)"
2024-01-31 10:36:08 +01:00
exit 1
fi
logger INFO "Found PyGObject in Python env"
2022-05-09 13:42:24 +02:00
}
2024-01-31 10:36:08 +01:00
update_config(){
# handling for legacy files
[[ -z $branch ]] && branch="stable"
[[ -f $config_file ]] && mv $config_file ${config_file}.old
write_config > $config_file && return 90 || return 1
logger INFO "Updated config file at '$config_file'"
}
setup_steam_client(){
local flatpak
local steam
local steam_cmd
[[ -n $preferred_client ]] && return 0
[[ $(command -v flatpak) ]] && flatpak=$(flatpak list | grep valvesoftware.Steam)
steam=$(command -v steam)
if [[ -z "$steam" ]] && [[ -z "$flatpak" ]]; then
raise_error_and_quit "Requires Steam or Flatpak Steam"
elif [[ -n "$steam" ]] && [[ -n "$flatpak" ]]; then
preferred_client="steam"
elif [[ -n "$steam" ]]; then
preferred_client="steam"
else
steam_cmd="flatpak run com.valvesoftware.Steam"
fi
update_config && logger INFO "Preferred client set to '$steam_cmd'" || return 1
2022-05-22 21:20:34 +02:00
}
2024-01-31 10:36:08 +01:00
print_ip_list(){
[[ ${#ip_list[@]} -eq 0 ]] && return 1
printf "\t\"%s\"\n" "${ip_list[@]}"
2022-08-11 00:59:29 +02:00
}
2022-05-22 21:20:34 +02:00
write_config(){
2024-01-31 10:36:08 +01:00
cat <<-END
2022-06-15 12:32:10 +02:00
#Path to DayZ installation
steam_path="$steam_path"
2022-05-22 21:20:34 +02:00
2024-01-31 10:36:08 +01:00
#Battlemetrics API key
2022-06-15 12:32:10 +02:00
api_key="$api_key"
2022-05-22 21:20:34 +02:00
2023-11-15 11:53:11 +01:00
#Favorited server IP:PORT array
ip_list=(
2024-01-31 10:36:08 +01:00
$(print_ip_list)
2023-11-15 11:53:11 +01:00
)
2022-05-22 21:20:34 +02:00
#Favorite server to fast-connect to (limit one)
2023-11-15 11:53:11 +01:00
fav_server="$fav_server"
#Favorite server label (human readable)
fav_label="$fav_label"
2022-05-22 21:20:34 +02:00
#Custom player name (optional, required by some servers)
2022-06-15 12:32:10 +02:00
name="$name"
2022-05-22 21:20:34 +02:00
#Set to 1 to perform dry-run and print launch options
2022-07-31 20:01:58 +02:00
debug="$debug"
2022-07-18 10:58:38 +02:00
#Toggle stable/testing branch
2022-07-31 19:52:59 +02:00
branch="$branch"
2022-07-24 15:20:06 +02:00
2024-10-31 16:11:09 +01:00
#Start in fullscreen
fullscreen="$fullscreen"
2022-08-16 17:49:51 +02:00
#Steam API key
2022-08-31 10:22:07 +02:00
steam_api="$steam_api"
2022-10-05 10:08:47 +02:00
2022-10-06 14:50:37 +02:00
#Auto-install mods
auto_install="$auto_install"
#Automod staging directory
2022-10-07 09:26:39 +02:00
staging_dir="$staging_dir"
2022-10-23 20:09:35 +02:00
#Path to default Steam client
default_steam_path="$default_steam_path"
#Preferred Steam launch command (for Flatpak support)
2023-01-19 17:55:41 +01:00
preferred_client="$preferred_client"
2024-01-31 10:36:08 +01:00
#DZGUI source path
src_path="$src_path"
END
}
depcheck(){
for dep in "${!deps[@]}"; do
command -v "$dep" 2>&1>/dev/null
if [[ $? -eq 1 ]]; then
local msg="Requires $dep >= ${deps[$dep]}"
raise_error_and_quit "$msg"
fi
done
2024-09-10 07:42:51 +02:00
local jqmsg="jq must be compiled with support for oniguruma"
local jqtest
jqtest=$(echo '{"test": "foo"}' | jq '.test | test("^foo$")')
[[ $? -ne 0 ]] && raise_error_and_quit "$jqmsg"
2024-01-31 10:36:08 +01:00
logger INFO "Initial dependencies satisfied"
}
check_pyver(){
local pyver=$(python3 --version | awk '{print $2}')
local minor=$(<<< $pyver awk -F. '{print $2}')
if [[ -z $pyver ]] || [[ ${pyver:0:1} -lt 3 ]] || [[ $minor -lt 10 ]]; then
local msg="Requires Python >=3.10"
raise_error_and_quit "$msg"
fi
logger INFO "Found Python version: $pyver"
}
watcher_deps(){
if [[ ! $(command -v wmctrl) ]] && [[ ! $(command -v xdotool) ]]; then
raise_error_and_quit "Missing dependency: requires 'wmctrl' or 'xdotool'"
exit 1
fi
logger INFO "Found DZG Watcher dependencies"
}
format_version_url(){
2024-06-15 19:57:28 +02:00
[[ -z "$branch" ]] && branch="stable"
2024-01-31 10:36:08 +01:00
case "$branch" in
"stable")
version_url="$stable_url/dzgui.sh"
;;
"testing")
version_url="$testing_url/dzgui.sh"
;;
esac
echo "$version_url"
2022-05-22 21:20:34 +02:00
}
2022-08-04 21:14:56 +02:00
write_desktop_file(){
2024-01-31 10:36:08 +01:00
cat <<-END
2022-08-04 21:14:56 +02:00
[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
2024-01-31 10:36:08 +01:00
Exec=$share_path/dzgui.sh
Name=$app_name_upper
2024-01-31 10:51:55 +01:00
Comment=$app_name
Icon=$share_path/$app_name
2022-08-05 20:03:24 +02:00
Categories=Game
2024-01-31 10:36:08 +01:00
END
2022-08-04 21:14:56 +02:00
}
2022-08-05 21:58:59 +02:00
freedesktop_dirs(){
2024-01-31 10:36:08 +01:00
local version_url=$(format_version_url)
local img_url="$stable_url/images"
curl -s "$version_url" > "$script_path"
chmod +x "$script_path"
2024-04-19 00:22:41 +02:00
for i in dzgui grid.png hero.png logo.png icon.png; do
2024-01-31 10:36:08 +01:00
curl -s "$img_url/$i" > "$share_path/$i"
done
2024-01-31 10:51:55 +01:00
write_desktop_file > "$freedesktop_path/$app_name.desktop"
2024-01-31 10:36:08 +01:00
[[ $is_steam_deck -eq 0 ]] && return
2024-01-31 10:51:55 +01:00
write_desktop_file > "$HOME/Desktop/$app_name.desktop"
2024-01-31 10:36:08 +01:00
}
legacy_vars(){
local suffix="fav"
local hr_msg="Config file contains values based on old API. Please update and re-run setup."
local msg="Config file contains legacy API value: '$suffix'"
if [[ -n $fav ]]; then
logger WARN "$msg"
fdialog "$hr_msg"
exit 1
fi
if [[ -n $whitelist ]]; then
suffix="whitelist"
logger WARN "$msg"
fdialog "$hr_msg"
exit 1
fi
2022-05-22 21:20:34 +02:00
}
2024-01-31 10:36:08 +01:00
merge_config(){
[[ -z $staging_dir ]] && staging_dir="/tmp"
update_config
tdialog "Wrote new config format to \n${config_file}\nIf errors occur, you can restore the file:\n${config_file}.old"
2022-06-15 12:32:10 +02:00
}
2024-01-31 10:36:08 +01:00
check_unmerged(){
if [[ -f ${config_path}.unmerged ]]; then
merge_config
rm ${config_path}.unmerged
fi
2023-05-16 00:14:56 +02:00
}
2024-01-31 10:36:08 +01:00
check_version(){
local version_url=$(format_version_url)
local upstream=$(curl -Ls "$version_url" | awk -F= '/^version=/ {print $2}')
local res=$(get_response_code "$version_url")
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$version_url'"
2024-01-31 10:36:08 +01:00
logger INFO "Local branch: '$branch', local version: $version"
if [[ $branch == "stable" ]]; then
version_url="$stable_url/dzgui.sh"
elif [[ $branch == "testing" ]]; then
version_url="$testing_url/dzgui.sh"
fi
2024-01-31 10:51:55 +01:00
[[ ! -f "$freedesktop_path/$app_name.desktop" ]] && freedesktop_dirs
2024-01-31 10:36:08 +01:00
if [[ $version == $upstream ]]; then
logger INFO "Local version is same as upstream"
check_unmerged
else
logger WARN "Local and remote version mismatch: $version != $upstream"
prompt_dl
fi
2022-11-28 20:52:25 +01:00
}
2024-01-31 10:36:08 +01:00
download_new_version(){
local version_url="$(format_version_url)"
logger INFO "Version URL is '$version_url'"
logger INFO "$src_path"
mv "$src_path" "$src_path.old"
curl -L "$version_url" > "$src_path" 2>$debug_log
rc=$?
if [[ $rc -eq 0 ]]; then
dl_changelog
logger INFO "Wrote new version to $src_path"
chmod +x "$src_path"
touch "${config_path}.unmerged"
fdialog "DZGUI $upstream successfully downloaded. To use the new version, select Exit and restart."
logger INFO "User exited after version upgrade"
exit 0
else
mv "$src_path.old" "$src_path"
logger WARN "curl failed to fetch new version. Rolling back"
fdialog "Failed to download the new version. Restoring old version"
return 1
fi
2022-05-22 21:20:34 +02:00
}
2024-01-31 10:36:08 +01:00
prompt_dl(){
_text(){
cat <<-EOF
Version conflict.
Your branch: $branch
Your version: $version
Upstream version: $upstream
Version updates introduce important bug fixes and are encouraged. Attempt to download the latest version?
EOF
}
qdialog "$(_text)" "Yes" "No"
if [[ $? -eq 1 ]]; then
return 0
else
download_new_version
fi
2022-05-22 21:20:34 +02:00
}
2024-01-31 10:36:08 +01:00
dl_changelog(){
local mdbranch
2024-12-12 03:08:07 +01:00
local md
2024-01-31 10:36:08 +01:00
[[ $branch == "stable" ]] && mdbranch="dzgui"
[[ $branch == "testing" ]] && mdbranch="testing"
local md="$url_prefix/${mdbranch}/$file"
2024-01-31 10:36:08 +01:00
curl -Ls "$md" > "$state_path/CHANGELOG.md"
2022-10-08 14:12:22 +02:00
}
test_display_mode(){
2024-01-31 10:36:08 +01:00
pgrep -a gamescope | grep -q "generate-drm-mode"
if [[ $? -eq 0 ]]; then
2023-12-02 14:37:37 +01:00
echo gm
else
echo dm
fi
2022-10-08 14:12:22 +02:00
}
2024-01-31 10:36:08 +01:00
check_architecture(){
2024-08-27 23:52:01 +02:00
local cpu=$(< /proc/cpuinfo awk -F": " '/AMD Custom APU [0-9]{4}$/ {print $2; exit}')
read -a APU_MODEL <<< "$cpu"
2024-08-28 00:52:20 +02:00
if [[ ${APU_MODEL[3]} != "0932" ]] && [[ ${APU_MODEL[3]} != "0405" ]]; then
2024-01-31 10:36:08 +01:00
is_steam_deck=0
logger INFO "Setting architecture to 'desktop'"
2024-08-27 23:52:01 +02:00
return
fi
if [[ $(test_display_mode) == "gm" ]]; then
is_steam_deck=2
else
is_steam_deck=1
2023-11-15 11:53:11 +01:00
fi
2024-08-27 23:52:01 +02:00
logger INFO "Setting architecture to 'Steam Deck'"
2022-06-04 22:29:30 +02:00
}
2024-01-31 10:36:08 +01:00
check_map_count(){
[[ $is_steam_deck -gt 0 ]] && return 0
local count=1048576
local conf_file="/etc/sysctl.d/dayz.conf"
if [[ -f $conf_file ]]; then
logger DEBUG "System map count is already $count or higher"
return 0
2023-11-15 11:53:11 +01:00
fi
2024-01-31 10:36:08 +01:00
qdialog "sudo password required to check system vm map count." "OK" "Cancel"
if [[ $? -eq 0 ]]; then
local pass
logger INFO "Prompting user for sudo escalation"
pass=$($steamsafe_zenity --password)
2023-11-15 11:53:11 +01:00
if [[ $? -eq 1 ]]; then
2024-01-31 10:36:08 +01:00
logger WARN "User aborted password prompt"
2023-11-15 11:53:11 +01:00
return 1
fi
2024-01-31 10:36:08 +01:00
local ct=$(sudo -S <<< "$pass" sh -c "sysctl -q vm.max_map_count | awk -F'= ' '{print \$2}'")
logger DEBUG "Old map count is $ct"
local new_ct
[[ $ct -lt $count ]] && ct=$count
sudo -S <<< "$pass" sh -c "echo 'vm.max_map_count=$ct' > $conf_file"
sudo sysctl -p "$conf_file"
logger DEBUG "Updated map count to $count"
else
logger WARN "User aborted map count prompt"
return 1
2023-11-15 11:53:11 +01:00
fi
2022-06-15 12:32:10 +02:00
}
2024-01-31 10:36:08 +01:00
qdialog(){
local text="$1"
local ok="$2"
local cancel="$3"
$steamsafe_zenity --question --text="$1" --ok-label="$ok" --cancel-label="$cancel" "${zenity_flags[@]}"
2023-05-19 16:29:21 +02:00
}
2024-01-31 10:36:08 +01:00
pdialog(){
$steamsafe_zenity --progress --pulsate --auto-close "${zenity_flags[@]}" --text="$1"
2023-05-19 16:29:21 +02:00
}
2024-01-31 10:36:08 +01:00
fdialog(){
$steamsafe_zenity --warning --ok-label="Exit" --text="$1" "${zenity_flags[@]}"
2022-05-22 21:20:34 +02:00
}
2024-01-31 10:36:08 +01:00
tdialog(){
$steamsafe_zenity --info --text="$1" "${zenity_flags[@]}"
2022-05-22 21:20:34 +02:00
}
2024-01-31 10:36:08 +01:00
steam_deps(){
local flatpak
local steam
[[ $(command -v flatpak) ]] && flatpak=$(flatpak list | grep valvesoftware.Steam)
steam=$(command -v steam)
if [[ -z "$steam" ]] && [[ -z "$flatpak" ]]; then
local msg="Found neither Steam nor Flatpak Steam"
raise_error_and_quit "$msg"
exit 1
elif [[ -n "$steam" ]] && [[ -n "$flatpak" ]]; then
[[ -n $preferred_client ]] && return 0
if [[ -z $preferred_client ]]; then
preferred_client="steam"
2023-11-15 11:53:11 +01:00
fi
2024-01-31 10:36:08 +01:00
elif [[ -n "$steam" ]]; then
preferred_client="steam"
else
preferred_client="flatpak"
2023-11-22 10:33:50 +01:00
fi
2023-11-15 11:53:11 +01:00
update_config
2024-01-31 10:36:08 +01:00
logger INFO "Preferred client set to '$preferred_client'"
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
migrate_files(){
if [[ ! -f $config_path/dztuirc.oldapi ]]; then
cp $config_file $config_path/dztuirc.oldapi
logger INFO "Migrated old API file"
fi
[[ ! -f $hist_file ]] && return
rm $hist_file
logger INFO "Wiped old history file"
2022-06-04 22:29:30 +02:00
}
2024-01-31 10:36:08 +01:00
stale_symlinks(){
local game_dir="$steam_path/steamapps/common/DayZ"
for l in $(find "$game_dir" -xtype l); do
logger DEBUG "Updating stale symlink '$l'"
2024-12-15 00:57:25 +01:00
unlink "$l"
2024-01-31 10:36:08 +01:00
done
2022-07-18 10:58:38 +02:00
}
2024-01-31 10:36:08 +01:00
local_latlon(){
if [[ -z $(command -v dig) ]]; then
local local_ip=$(curl -Ls "https://ipecho.net/plain")
else
local local_ip=$(dig -4 +short myip.opendns.com @resolver1.opendns.com)
fi
local url="http://ip-api.com/json/$local_ip"
local res=$(curl -Ls "$url" | jq -r '"\(.lat)\n\(.lon)"')
if [[ -z "$res" ]]; then
logger WARN "Failed to get local coordinates"
return 1
fi
echo "$res" > "$coords_file"
2022-07-18 10:58:38 +02:00
}
2024-01-31 10:36:08 +01:00
lock(){
[[ ! -f $lock_file ]] && touch $lock_file
local pid=$(cat $lock_file)
ps -p $pid -o pid= >/dev/null 2>&1
res=$?
if [[ $res -eq 0 ]]; then
local msg="DZGUI already running ($pid)"
raise_error_and_quit "$msg"
elif [[ $pid == $$ ]]; then
:
else
echo $$ > $lock_file
fi
2023-05-11 05:10:27 +02:00
}
2024-01-31 10:36:08 +01:00
get_hash(){
local file="$1"
md5sum "$1" | awk '{print $1}'
2023-05-11 05:10:27 +02:00
}
2024-01-31 10:36:08 +01:00
fetch_a2s(){
# this file is currently monolithic
2024-01-31 10:36:08 +01:00
[[ -d $helpers_path/a2s ]] && { logger INFO "A2S helper is current"; return 0; }
local sha=c7590ffa9a6d0c6912e17ceeab15b832a1090640
local author="yepoleb"
local repo="python-a2s"
local url="https://github.com/$author/$repo/tarball/$sha"
local prefix="${author^}-$repo-${sha:0:7}"
local file="$prefix.tar.gz"
local res=$(get_response_code "$url")
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$file'"
2024-01-31 10:36:08 +01:00
curl -Ls "$url" > "$helpers_path/$file"
tar xf "$helpers_path/$file" -C "$helpers_path" "$prefix/a2s" --strip=1
rm "$helpers_path/$file"
logger INFO "Updated A2S helper to sha '$sha'"
2022-10-23 20:09:35 +02:00
}
2024-01-31 10:36:08 +01:00
fetch_dzq(){
2024-10-30 14:58:56 +01:00
local sum="9caed1445c45832f4af87736ba3f9637"
2024-01-31 10:36:08 +01:00
local file="$helpers_path/a2s/dayzquery.py"
if [[ -f $file ]] && [[ $(get_hash "$file") == $sum ]]; then
logger INFO "DZQ is current"
return 0
fi
2024-11-03 14:22:46 +01:00
local sha=3088bbfb147b77bc7b6a9425581b439889ff3f7f
2024-12-12 01:54:44 +01:00
local author="yepoleb"
2024-01-31 10:36:08 +01:00
local repo="dayzquery"
local url="https://raw.githubusercontent.com/$author/$repo/$sha/dayzquery.py"
local res=$(get_response_code "$url")
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: 'dayzquery.py'"
2024-01-31 10:36:08 +01:00
curl -Ls "$url" > "$file"
logger INFO "Updated DZQ to sha '$sha'"
}
2024-08-27 23:52:01 +02:00
fetch_icons(){
res=(
"16"
"24"
"32"
"48"
"64"
"96"
"128"
"256"
)
2024-10-05 20:19:32 +02:00
url="$stable_url/images/icons"
2024-08-27 23:52:01 +02:00
for i in "${res[@]}"; do
size="${i}x${i}"
dir="$HOME/.local/share/icons/hicolor/$size/apps"
icon="$dir/$app_name.png"
[[ -f $icon ]] && return
if [[ ! -d $dir ]]; then
mkdir -p "$dir"
fi
logger INFO "Updating $size Freedesktop icon"
curl -Ls "${url}/${i}.png" > "$icon"
done
}
2024-01-31 10:36:08 +01:00
fetch_helpers_by_sum(){
2024-06-15 19:57:28 +02:00
[[ -f "$config_file" ]] && source "$config_file"
2024-01-31 10:36:08 +01:00
declare -A sums
sums=(
2024-12-15 01:08:35 +01:00
["ui.py"]="24d0525e71c0725a1487926fae7330e4"
2024-08-04 23:03:15 +02:00
["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
2024-01-31 10:36:08 +01:00
["vdf2json.py"]="2f49f6f5d3af919bebaab2e9c220f397"
2024-12-15 01:08:35 +01:00
["funcs"]="4c1480fcfae15c4bc1c02a337d1de488"
2024-08-04 23:03:15 +02:00
["lan"]="c62e84ddd1457b71a85ad21da662b9af"
2024-01-31 10:36:08 +01:00
)
local author="aclist"
local repo="dztui"
2024-01-31 10:36:08 +01:00
local realbranch
local file
local sum
local full_path
# first time setup
if [[ -z $branch ]]; then
realbranch="dzgui"
else
realbranch="$branch"
fi
2024-03-18 11:53:06 +01:00
if [[ $realbranch == "stable" ]]; then
realbranch="dzgui"
fi
2023-05-16 13:05:36 +02:00
2024-01-31 10:36:08 +01:00
for i in "${!sums[@]}"; do
file="$i"
sum="${sums[$i]}"
full_path="$helpers_path/$file"
2024-12-12 03:08:07 +01:00
2024-12-13 01:58:44 +01:00
url="${url_prefix}/$realbranch/helpers/$file"
2024-12-12 03:08:07 +01:00
2024-01-31 10:36:08 +01:00
if [[ -f "$full_path" ]] && [[ $(get_hash "$full_path") == $sum ]]; then
logger INFO "$file is current"
else
logger WARN "File '$full_path' checksum != '$sum'"
local res=$(get_response_code "$url")
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$url'"
2024-01-31 10:36:08 +01:00
curl -Ls "$url" > "$full_path"
if [[ ! $? -eq 0 ]]; then
raise_error_and_quit "Failed to fetch the file '$file'. Possible timeout?"
2023-11-15 11:53:11 +01:00
fi
2024-01-31 10:36:08 +01:00
if [[ $(get_hash $full_path) != $sum ]]; then
logger WARN "Downloaded new '$file', but checksum != '$sum'"
2023-11-15 11:53:11 +01:00
fi
2024-01-31 10:36:08 +01:00
logger INFO "Updated '$full_path' to sum '$sum'"
fi
[[ $file == "funcs" ]] && chmod +x "$full_path"
2024-08-06 06:27:53 +02:00
[[ $file == "lan" ]] && chmod +x "$full_path"
2023-11-15 11:53:11 +01:00
done
2024-01-31 10:36:08 +01:00
return 0
}
fetch_geo_file(){
# for binary releases
2024-04-23 04:59:42 +02:00
local geo_sum="7b6668eb4535bb432acb42016ba9cc47"
2024-01-31 10:36:08 +01:00
local km_sum="b038fdb8f655798207bd28de3a004706"
local gzip="$helpers_path/ips.csv.gz"
if [[ ! -f $geo_file ]] || [[ $(get_hash $geo_file) != $geo_sum ]]; then
local res=$(get_response_code "$geo_file_url")
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$geo_file_url'"
2024-01-31 10:36:08 +01:00
curl -Ls "$geo_file_url" > "$gzip"
2023-11-15 11:53:11 +01:00
#force overwrite
gunzip -f "$gzip"
2024-01-31 10:36:08 +01:00
fi
if [[ ! -f $km_helper ]] || [[ $(get_hash $km_helper) != $km_sum ]]; then
local res=$(get_response_code "$km_helper_url")
[[ $res -ne 200 ]] && raise_error_and_quit "Remote resource unavailable: '$km_helper_url'"
2023-11-15 11:53:11 +01:00
curl -Ls "$km_helper_url" > "$km_helper"
2024-01-31 10:36:08 +01:00
chmod +x "$km_helper"
2023-11-18 06:37:15 +01:00
fi
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
fetch_helpers(){
fetch_a2s
fetch_dzq
fetch_geo_file
fetch_helpers_by_sum
2024-04-19 00:22:41 +02:00
[[ ! -f $share_path/icon.png ]] && freedesktop_dirs
2024-08-27 23:56:17 +02:00
fetch_icons
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
raise_error_and_quit(){
local msg="$1"
logger CRITICAL "$msg"
fdialog "$msg"
exit 1
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
test_steam_api(){
local key="$1"
[[ -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")
2024-06-10 19:15:23 +02:00
[[ ! $code =~ 200 ]] && echo 1
2024-01-31 10:36:08 +01:00
[[ $code =~ 200 ]] && echo 0
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
test_bm_api(){
local bm_api="https://api.battlemetrics.com/servers"
local key="$1"
[[ -z $key ]] && return 1
local code=$(curl -ILs "$bm_api" \
-H "Authorization: Bearer "$key"" -G \
2023-11-15 11:53:11 +01:00
-d "filter[game]=$game" \
2024-01-31 10:36:08 +01:00
| grep -E "^HTTP")
[[ $code =~ 401 ]] && echo 1
[[ $code =~ 200 ]] && echo 0
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
find_default_path(){
_discover(){
2024-06-10 19:15:23 +02:00
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 \
2024-06-15 20:29:04 +02:00
-o -regex ".*Steam/config/libraryfolders.vdf$" -print 2>/dev/null | sed 's@/config/libraryfolders.vdf@@')
2024-06-10 19:15:23 +02:00
if [[ "${#paths[@]}" -gt 1 ]]; then
2024-06-15 20:29:04 +02:00
echo "100"
2024-06-12 18:42:34 +02:00
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")
2024-06-15 20:29:04 +02:00
[[ -z "$default_steam_path" ]] && exit 1
2024-06-10 19:15:23 +02:00
else
default_steam_path="${paths[0]}"
fi
2024-01-31 10:36:08 +01:00
}
2024-01-31 11:49:29 +01:00
if [[ $is_steam_deck -gt 0 ]]; then
2024-01-31 10:36:08 +01:00
default_steam_path="$HOME/.local/share/Steam"
logger INFO "Set default Steam path to $default_steam_path"
2023-11-15 11:53:11 +01:00
return 0
fi
2024-01-31 10:36:08 +01:00
local def_path
local ubuntu_path
local flatpak_path
local debian_path
def_path="$HOME/.local/share/Steam"
ubuntu_path="$HOME/.steam/steam"
debian_path="$HOME/.steam/debian-installation"
flatpak_path="$HOME/.var/app/com.valvesoftware.Steam/data/Steam"
#ubuntu path must precede default path because
#both exist on ubuntu systems, but only ubuntu path contains library data
for i in "$ubuntu_path" "$def_path" "$debian_path" "$flatpak_path"; do
2024-01-31 10:36:08 +01:00
if [[ -d "$i" ]]; then
default_steam_path="$i"
return 0
2023-11-15 11:53:11 +01:00
fi
done
2024-01-31 10:36:08 +01:00
local msg="Let DZGUI auto-discover Steam path (accurate, slower)\nSelect the Steam path manually (less accurate, faster)"
2024-06-15 20:29:04 +02:00
local res=$(echo -e "$msg" | $steamsafe_zenity --list \
2024-01-31 10:36:08 +01:00
--column="Choice" \
--title="DZGUI" \
--hide-header \
--text="Steam is not installed in a standard location." \
2024-06-15 20:29:04 +02:00
$sd_res)
2024-01-31 10:36:08 +01:00
case "$res" in
2024-06-15 20:29:04 +02:00
*auto*) _discover > >(pdialog "Scanning paths") ;;
2024-01-31 10:36:08 +01:00
*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 ;;
esac
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
file_picker(){
local path=$($steamsafe_zenity --file-selection --directory)
logger INFO "File picker path resolved to: $path"
if [[ -z "$path" ]]; then
logger WARN "Steam path selection was empty"
return
2023-12-02 14:37:37 +01:00
else
2024-01-31 10:36:08 +01:00
default_steam_path="$path"
2023-12-02 14:37:37 +01:00
fi
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
find_library_folder(){
local search_path="$1"
steam_path="$(python3 "$helpers_path/vdf2json.py" -i "$1/steamapps/libraryfolders.vdf" \
| jq -r '.libraryfolders[]|select(.apps|has("221100")).path')"
if [[ ! $? -eq 0 ]]; then
logger WARN "Failed to parse Steam path using '$search_path'"
return 1
fi
logger INFO "Steam path resolved to: $steam_path"
2023-11-15 11:53:11 +01:00
}
2024-01-31 10:36:08 +01:00
create_config(){
2024-05-29 07:36:01 +02:00
#if old path is malformed and this function is forcibly called,
#wipe paths from memory before entering the loop to force path rediscovery
unset default_steam_path
unset steam_path
2024-01-31 10:36:08 +01:00
while true; do
local player_input="$($steamsafe_zenity \
--forms \
--add-entry="Player name (required for some servers)" \
--add-entry="Steam API key" \
--add-entry="BattleMetrics API key (optional)" \
--title="DZGUI" \
--text="DZGUI" $sd_res \
--separator="@")"
#explicitly setting IFS crashes $steamsafe_zenity in loop
2024-05-29 07:36:01 +02:00
#and mapfile does not support high ascii delimiters, so split fields with newline
2024-01-31 10:36:08 +01:00
readarray -t args < <(<<< "$player_input" sed 's/@/\n/g')
name="${args[0]}"
steam_api="${args[1]}"
api_key="${args[2]}"
if [[ -z $player_input ]]; then
logger WARN "User aborted setup process"
exit 1
fi
if [[ -z $steam_api ]]; then
tdialog "Steam API key canot be empty"
continue
elif [[ "${#steam_api}" -lt 32 ]] || [[ $(test_steam_api "$steam_api") -eq 1 ]]; then
tdialog "Invalid Steam API key"
continue
fi
if [[ -n $api_key ]] && [[ $(test_bm_api $api_key) -eq 1 ]]; then
tdialog "Invalid BM API key"
continue
fi
2023-11-15 11:53:11 +01:00
while true; do
2024-01-31 10:36:08 +01:00
if [[ -n $steam_path ]]; then
write_config
[[ $? -eq 0 ]] && logger INFO "Successfully created config file"
return 0
fi
find_default_path
find_library_folder "$default_steam_path"
if [[ -z $steam_path ]]; then
logger raise_error "Steam path was empty"
2024-05-29 07:36:01 +02:00
zenity --question --text="DayZ not found or not installed at the Steam library given." --ok-label="Choose path manually" --cancel-label="Exit"
2024-01-31 10:36:08 +01:00
if [[ $? -eq 0 ]]; then
logger INFO "User selected file picker"
file_picker
find_library_folder "$default_steam_path"
else
fdialog "Failed to find Steam at the provided location"
exit 1
fi
else
branch="stable"
update_config
logger INFO "Wrote config to '$config_file'"
return 0
2023-11-15 11:53:11 +01:00
fi
done
2024-01-31 10:36:08 +01:00
done
}
varcheck(){
local msg="Config file '$config_file' missing. Start first-time setup now?"
local msg2="The Steam paths set in your config file appear to be invalid. Restart first-time setup now?"
if [[ ! -f $config_file ]]; then
qdialog "$msg" "Yes" "Exit"
if [[ $? -eq 1 ]]; then
logger CRITICAL "Config file missing, but user aborted setup"
exit 1
fi
create_config
2023-11-15 11:53:11 +01:00
fi
2024-01-31 10:36:08 +01:00
source "$config_file"
local workshop_dir="$steam_path/steamapps/workshop/content/$aid"
local game_dir="$steam_path/steamapps/common/DayZ"
2024-07-18 18:06:13 +02:00
if [[ ! -d $steam_path ]] || [[ ! -d $game_dir ]] || [[ ! $(find $game_dir -type f) ]]; then
2024-01-31 10:36:08 +01:00
logger WARN "DayZ path resolved to '$game_dir'"
logger WARN "Workshop path resolved to '$workshop_dir'"
qdialog "$msg2" "Yes" "Exit"
if [[ $? -eq 1 ]]; then
logger CRITICAL "Malformed Steam path, but user aborted setup"
exit 1
2023-11-15 11:53:11 +01:00
fi
2024-01-31 10:36:08 +01:00
create_config
return 0
fi
if [[ $src_path != $(realpath "$0") ]]; then
src_path=$(realpath "$0")
2023-11-15 11:53:11 +01:00
update_config
2023-11-23 05:24:16 +01:00
fi
2022-10-11 13:58:00 +02:00
}
2024-01-31 10:36:08 +01:00
is_dzg_downloading(){
if [[ -d $steam_path ]] && [[ -d $steam_path/downloading/$aid ]]; then
logger WARN "DayZ may be scheduling updates"
return 0
fi
2023-01-19 12:20:30 +01:00
}
2024-01-31 10:36:08 +01:00
is_steam_running(){
local res=$(ps aux | grep "steamwebhelper" | grep -v grep)
if [[ -z $res ]]; then
logger WARN "Steam may not be running"
tdialog "Is Steam running? For best results, make sure Steam is open in the background."
return 0
fi
2023-01-19 18:05:11 +01:00
}
2024-12-12 03:08:07 +01:00
get_response_code(){
local url="$1"
curl -Ls -I -o /dev/null -w "%{http_code}" "$url"
}
2024-01-31 10:36:08 +01:00
test_connection(){
2024-12-12 03:08:07 +01:00
source "$config_file"
declare -A hr
local res1
local res2
local str="No connection could be established to the remote server"
hr=(
["steampowered.com"]="https://api.steampowered.com/IGameServersService/GetServerList/v1/?key=$steam_api"
["github.com"]="https://github.com/$author"
["codeberg.org"]="https://codeberg.org/$author"
)
2024-12-12 03:50:18 +01:00
# steam API is mandatory, except on initial setup
if [[ -n $steam_api ]]; then
res=$(get_response_code "${hr["steampowered.com"]}")
[[ $res -ne 200 ]] && raise_error_and_quit "$str ("steampowered.com")"
fi
2024-12-12 03:08:07 +01:00
2024-12-12 03:16:46 +01:00
res=$(get_response_code "${hr["github.com"]}")
if [[ $res -ne 200 ]]; then
logger WARN "Remote host '${hr["github.com"]}' unreachable', trying fallback"
remote_host=cb
res=$(get_response_code "${hr["codeberg.org"]}")
[[ $res -ne 200 ]] && raise_error_and_quit "$str (${hr["codeberg.org"]})"
fi
logger INFO "Set remote host to '${hr["codeberg.org"]}'"
2024-12-12 03:08:07 +01:00
if [[ $remote_host == "cb" ]]; then
url_prefix="https://codeberg.org/$author/$repo/raw/branch"
releases_url="https://codeberg.org/$author/$repo/releases/download/browser"
2024-12-12 03:25:39 +01:00
stable_url="$url_prefix/dzgui"
testing_url="$url_prefix/testing"
km_helper_url="$releases_url/latlon"
geo_file_url="$releases_url/ips.csv.gz"
2024-01-31 10:36:08 +01:00
fi
2023-01-19 12:11:38 +01:00
}
2024-06-10 19:15:23 +02:00
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
}
2024-11-15 23:42:52 +01:00
stale_mod_signatures(){
local workshop_dir="$steam_path/steamapps/workshop/content/$aid"
if [[ -d $workshop_dir ]]; then
readarray -t old_mod_ids < <(awk -F, '{print $1}' $versions_file)
for ((i=0; i<${#old_mod_ids[@]}; ++i)); do
if [[ ! -d $workshop_dir/${old_mod_ids[$i]} ]]; then
"$HOME/.local/share/$app_name/helpers/funcs" "align_local" "${old_mod_ids[$i]}"
fi
done
fi
}
2024-11-19 13:49:59 +01:00
create_new_links(){
"$HOME/.local/share/$app_name/helpers/funcs" "update_symlinks"
}
2022-09-24 11:49:01 +02:00
initial_setup(){
2024-01-31 10:36:08 +01:00
setup_dirs
setup_state_files
depcheck
check_pyver
test_gobject
watcher_deps
check_architecture
test_connection
2024-11-21 09:34:47 +01:00
fetch_helpers > >(pdialog "Checking helper files")
2024-01-31 10:36:08 +01:00
varcheck
source "$config_file"
lock
legacy_vars
2024-06-10 19:15:23 +02:00
legacy_cols
2024-01-31 10:36:08 +01:00
check_version
check_map_count
steam_deps
2023-11-15 11:53:11 +01:00
migrate_files
2024-01-31 10:36:08 +01:00
stale_symlinks
2024-11-15 23:42:52 +01:00
stale_mod_signatures
2024-11-19 13:49:59 +01:00
create_new_links
2024-01-31 10:36:08 +01:00
local_latlon
is_steam_running
is_dzg_downloading
print_config_vals
2022-09-24 11:49:01 +02:00
}
2024-06-12 18:42:34 +02:00
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
2024-06-12 18:42:34 +02:00
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"
}
2022-09-24 11:49:01 +02:00
main(){
2024-01-31 10:36:08 +01:00
local zenv=$(zenity --version 2>/dev/null)
2024-08-27 23:52:01 +02:00
[[ -z $zenv ]] && { echo "Requires zenity >= ${deps[$steamsafe_zenity]}"; exit 1; }
2024-06-12 18:42:34 +02:00
if [[ $1 == "--uninstall" ]] || [[ $1 == "-u" ]]; then
uninstall &&
exit 0
fi
2024-01-31 10:36:08 +01:00
set_im_module
printf "Initializing setup...\n"
initial_setup
printf "All OK. Kicking off UI...\n"
python3 "$ui_helper" "--init-ui" "$version" "$is_steam_deck"
2022-05-09 13:42:24 +02:00
}
2024-06-12 18:42:34 +02:00
main "$@"
2024-01-31 10:36:08 +01:00
#TODO: tech debt: cruddy handling for steam forking
[[ $? -eq 1 ]] && pkill -f dzgui.sh