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-11-10 22:05:56 +01:00
version = 5.5.0
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"
2022-07-17 18:06:41 +02:00
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 "
#URLS
author = "aclist"
repo = "dztui"
url_prefix = " https://raw.githubusercontent.com/ $author / $repo "
stable_url = " $url_prefix /dzgui "
testing_url = " $url_prefix /testing "
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-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 "
2023-01-19 17:21:02 +01:00
#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}' )
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
local upstream = $( curl -Ls " $version_url " | awk -F= '/^version=/ {print $2}' )
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
[ [ $branch = = "stable" ] ] && mdbranch = "dzgui"
[ [ $branch = = "testing" ] ] && mdbranch = "testing"
local md = " https://raw.githubusercontent.com/ $author /dztui/ ${ mdbranch } /CHANGELOG.md "
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 ' "
unlink $l
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( ) {
[ [ -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 "
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-10-30 14:58:56 +01:00
local author = "aclist"
2024-01-31 10:36:08 +01:00
local repo = "dayzquery"
local url = " https://raw.githubusercontent.com/ $author / $repo / $sha /dayzquery.py "
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-11-03 14:22:46 +01:00
[ "ui.py" ] = "dd7aa34df1d374739127cca3033a3f67"
2024-08-04 23:03:15 +02:00
[ "query_v2.py" ] = "55d339ba02512ac69de288eb3be41067"
2024-01-31 10:36:08 +01:00
[ "vdf2json.py" ] = "2f49f6f5d3af919bebaab2e9c220f397"
2024-10-31 16:13:04 +01:00
[ "funcs" ] = "d8ae2662fbc3c62bdb5a51dec1935705"
2024-08-04 23:03:15 +02:00
[ "lan" ] = "c62e84ddd1457b71a85ad21da662b9af"
2024-01-31 10:36:08 +01:00
)
local author = "aclist"
local repo = "dztui"
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 "
url = " https://raw.githubusercontent.com/ $author / $repo / $realbranch /helpers/ $file "
if [ [ -f " $full_path " ] ] && [ [ $( get_hash " $full_path " ) = = $sum ] ] ; then
logger INFO " $file is current "
else
logger WARN " File ' $full_path ' checksum != ' $sum ' "
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
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
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 "
2024-07-02 07:27:37 +02:00
#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-01-31 10:36:08 +01:00
test_connection( ) {
ping -c1 -4 github.com 1>/dev/null 2>& 1
if [ [ ! $? -eq 0 ] ] ; then
raise_error_and_quit "No connection could be established to the remote server (github.com)."
fi
ping -c1 -4 api.steampowered.com 1>/dev/null 2>& 1
if [ [ ! $? -eq 0 ] ] ; then
raise_error_and_quit "No connection could be established to the remote server (steampowered.com)."
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
}
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-10-30 15:02:14 +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
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( ) {
2024-06-15 19:59:59 +02:00
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