Compare commits

...
7 Commits
Author SHA1 Message Date
aclist 84c75173a0 Update CONTRIBUTING.md
Mirror to Codeberg / mirror-to-codeberg (push) Has been cancelled
2026-07-07 16:50:39 +09:00
aclist 7528ab6fa3 Update CONTRIBUTING.md 2026-07-07 16:49:42 +09:00
aclist fa43459a78 chore: update actions to v5
Mirror to Codeberg / mirror-to-codeberg (push) Has been cancelled
2026-06-05 19:01:03 +09:00
aclist 252f07cbec Merge pull request #287 from aclist/prerelease/6.0.6-beta.1
Mirror to Codeberg / mirror-to-codeberg (push) Has been cancelled
chore: update symlink hash logic
2026-05-17 23:42:18 +09:00
aclist a0f610ead7 chore: update symlink hash logic 2026-05-17 23:40:35 +09:00
aclist ca4bcfc1a5 Merge pull request #285 from aclist/fix/server-mods-only
Mirror to Codeberg / mirror-to-codeberg (push) Has been cancelled
change: only update mods local to server
2026-04-17 20:57:03 +09:00
aclist ac4892d4f0 change: only update mods local to server 2026-04-17 20:47:25 +09:00
5 changed files with 166 additions and 156 deletions

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ jobs:
mirror-to-codeberg: mirror-to-codeberg:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v5
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: pixta-dev/repository-mirroring-action@v1 - uses: pixta-dev/repository-mirroring-action@v1
+9
View File
@@ -1,5 +1,14 @@
# Changelog # Changelog
## [6.0.6-beta.1] 2026-05-17
## Changed
- Update symlink hash logic to align with DZGUI 7 beta
- Update A2S helper to latest commit
## [6.0.5-beta.2] 2026-04-17
## Changed
- During server connection attempts, only download mods local to specific server
## [6.0.5-beta.1] 2026-04-13 ## [6.0.5-beta.1] 2026-04-13
## Fixed ## Fixed
- Update A2S module checksums to support servers with missing description field - Update A2S module checksums to support servers with missing description field
+3 -3
View File
@@ -8,7 +8,7 @@ If you are a developer, you can skip to the end.
# Requesting help # Requesting help
If you encounter a problem with DZGUI, you can submit tickets on the GitHub If you encounter a problem with DZGUI, you can submit tickets on the GitHub
(issue tracker)[https://github.com/aclist/dzgui-devel/issues] under the [issue tracker](https://github.com/aclist/dztui/issues) under the
`troubleshooting` tag. `troubleshooting` tag.
# How can I help the project? # How can I help the project?
@@ -24,7 +24,7 @@ accordingly.
## Submitting a ticket ## Submitting a ticket
Navigate to the GitHub (issue tracker)[https://github.com/aclist/dzgui-devel/issues]. Navigate to the GitHub [issue tracker](https://github.com/aclist/dztui/issues).
From there, follow the onscreen prompts. You will be asked questions such as: From there, follow the onscreen prompts. You will be asked questions such as:
- What version are you using? - What version are you using?
@@ -67,5 +67,5 @@ will be merged to `prerelease/<latest-version>`, then `testing`, and after a liv
testing phase, to `stable` as well. testing phase, to `stable` as well.
It is recommended to follow It is recommended to follow
(Conventional Commits)[https://www.conventionalcommits.org/en/v1.0.0/], as this [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/), as this
integrates well with tooling and helps the project review your code. integrates well with tooling and helps the project review your code.
+8 -5
View File
@@ -2,7 +2,7 @@
set -o pipefail set -o pipefail
src_path="$(readlink -e "$0")" src_path="$(readlink -e "$0")"
version=6.0.5-beta.1 version=6.0.6-beta.1
#CONSTANTS #CONSTANTS
aid=221100 aid=221100
@@ -567,9 +567,12 @@ get_hash(){
md5sum "$1" | awk '{print $1}' md5sum "$1" | awk '{print $1}'
} }
fetch_a2s(){ fetch_a2s(){
# this file is currently monolithic sum="d26da2fe03df2b95436f823f0496887b"
[[ -d $helpers_path/a2s ]] && { logger INFO "A2S helper is current"; return 0; } if [[ -d $helpers_path/a2s ]] && [[ $(get_hash "$helpers_path/a2s/info.py") == $sum ]]; then
local sha=c7590ffa9a6d0c6912e17ceeab15b832a1090640 logger INFO "A2S helper is current"
return 0
fi
local sha=b40eb24cdbb06ebd08272f224257fe5a81610e86
local author="yepoleb" local author="yepoleb"
local repo="python-a2s" local repo="python-a2s"
local url="https://github.com/$author/$repo/tarball/$sha" local url="https://github.com/$author/$repo/tarball/$sha"
@@ -626,7 +629,7 @@ fetch_helpers_by_sum(){
[[ -f "$config_file" ]] && source "$config_file" [[ -f "$config_file" ]] && source "$config_file"
declare -A sums declare -A sums
sums=( sums=(
["funcs"]="423d4406479430af3ce93aa906a90ed3" ["funcs"]="1cd26343cd68a5382e3377a9757497fa"
["query_v2.py"]="55d339ba02512ac69de288eb3be41067" ["query_v2.py"]="55d339ba02512ac69de288eb3be41067"
["servers.py"]="ed442c3aecf33f777d59dcf53650d263" ["servers.py"]="ed442c3aecf33f777d59dcf53650d263"
["ui.py"]="cf52a3d5883afe02a013d8673df494fa" ["ui.py"]="cf52a3d5883afe02a013d8673df494fa"
+145 -147
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -o pipefail set -o pipefail
version="6.0.5-beta.1" version="6.0.5-beta.2"
#CONSTANTS #CONSTANTS
aid=221100 aid=221100
@@ -690,6 +690,7 @@ toggle(){
auto_install="1" auto_install="1"
else else
auto_install="" auto_install=""
rm "$versions_file"
fi fi
;; ;;
Toggle[[:space:]]debug[[:space:]]mode) Toggle[[:space:]]debug[[:space:]]mode)
@@ -929,13 +930,19 @@ query_defunct(){
<<< "$result" awk '{print $2}' <<< "$result" awk '{print $2}'
} }
encode(){ encode(){
echo "$1" | md5sum | cut -c -8 echo -n "$1" | md5sum | cut -c -8
} }
compare(){ compare(){
local modlist="$@" local modlist="$@"
diff=$(comm -23 <(<<< "$modlist" sort -u) <(installed_mods | sort)) diff=$(comm -23 <(<<< "$modlist" sort -u) <(installed_mods | sort))
echo "$diff" echo "$diff"
} }
unlink_all(){
readarray -t links < <(find "$game_dir" -maxdepth 1 -mindepth 1 -type l)
for link in "${links[@]}"; do
unlink "$link"
done
}
legacy_symlinks(){ legacy_symlinks(){
logger INFO "Removing legacy symlinks" logger INFO "Removing legacy symlinks"
@@ -1026,7 +1033,10 @@ update_symlinks(){
if [[ ! -d "$workshop_dir" ]]; then if [[ ! -d "$workshop_dir" ]]; then
return return
fi fi
legacy_symlinks if [[ ! -d "$game_dir" ]]; then
return
fi
unlink_all
symlinks symlinks
} }
try_fallback(){ try_fallback(){
@@ -1077,41 +1087,42 @@ try_connect(){
local appid="$2" local appid="$2"
local binary="$3" local binary="$3"
local ip=$(<<< $record awk -F: '{print $1}') IFS=":" read -ra address <<< "$record"
local gameport=$(<<< $record awk -F: '{print $2}') local ip
local qport=$(<<< $record awk -F: '{print $3}') local gameport
local qport
ip=${address[0]}
gameport=${address[1]}
qport=${address[2]}
[[ $appid -eq $exp ]] && echo "$binary" > $_cache_binary [[ $appid -eq $exp ]] && echo "$binary" > "$_cache_binary"
local remote_mods local remote_mods
remote_mods=$(a2s $ip $qport rules) remote_mods=$(a2s "$ip" "$qport" rules)
if [[ $? -eq 1 ]]; then if [[ $? -eq 1 ]]; then
printf "Failed to fetch server modlist, possibly timed out" printf "Failed to fetch server modlist, possibly timed out"
return 1 return 1
fi fi
logger INFO "Server returned modlist: $(<<< $remote_mods tr '\n' ' ')" logger INFO "Server returned modlist: $(<<< "$remote_mods" tr '\n' ' ')"
local sanitized_mods=$(query_defunct "$remote_mods")
local diff=$(compare "$sanitized_mods") local sanitized_mods
sanitized_mods=$(query_defunct "$remote_mods")
logger INFO "Connection attempt for $ip:$qport" logger INFO "Connection attempt for $ip:$qport"
update_history "$record" update_history "$record"
if [[ -n $auto_install ]]; then case $auto_install in
logger INFO "Merging modlists" "") install_mods "$sanitized_mods" "manual" ;;
diff=$(merge_modlists "$diff") 1|2) install_mods "$sanitized_mods" "auto" ;;
diff=$(query_defunct "$diff") esac
fi
if [[ -n $diff ]]; then # NOTE: clean diff indicates that all requisite mods were downloaded
if [[ $(check_architecture) -eq 1 ]] && [[ $(test_display_mode) == "gm" ]]; then diff=$(compare "$sanitized_mods")
printf "Use Desktop Mode to download mods on Steam Deck" if [[ -z $diff ]]; then
return 1
fi
case $auto_install in
"") manual_mod_install "$ip" "$gameport" "$diff" "$sanitized_mods" "" "$appid";;
1|2) manual_mod_install "$ip" "$gameport" "$diff" "$sanitized_mods" "auto" "$appid" ;;
esac
else
launch "$ip" "$gameport" "$sanitized_mods" "$appid" launch "$ip" "$gameport" "$sanitized_mods" "$appid"
else
printf "User aborted download process, or some mods may have failed to download. Try connecting again to resync."
exit 1
fi fi
} }
check_architecture(){ check_architecture(){
@@ -1127,13 +1138,15 @@ force_update(){
printf "Only available when mod auto-install is ON" printf "Only available when mod auto-install is ON"
return 1 return 1
fi fi
# NOTE: forcibly regenerate signatures by removing file
rm "$versions_file" rm "$versions_file"
local update=$(check_timestamps) local mods
manual_mod_install "null" "null" "$update" "null" "force" "null" mods=$(ls -1 "$workshop_dir")
install_mods "$mods" "force"
echo "Finished requesting mod updates." echo "Finished requesting mod updates."
return 0 return 0
} }
get_local_stamps(){ get_timestamps(){
readarray -t modlist < <(printf "%s\n" "$@") readarray -t modlist < <(printf "%s\n" "$@")
local max="${#modlist[@]}" local max="${#modlist[@]}"
_concat(){ _concat(){
@@ -1158,67 +1171,6 @@ update_stamps(){
printf "%s\n" "${stamps[$i]}" >> $versions_file printf "%s\n" "${stamps[$i]}" >> $versions_file
done done
} }
check_timestamps(){
readarray -t local_modlist < <(ls -1 $workshop_dir)
local max=${#local_modlist[@]}
logger INFO "Local mod count: $max"
[[ $max -eq 0 ]] && return 1
local local_stamps=$(get_local_stamps "${local_modlist[@]}")
if [[ -z $local_stamps ]]; then
logger WARN "Timestamp query returned empty response"
return 1
fi
local aligned=$(<<< "$local_stamps" jq -r '.response.publishedfiledetails[]|"\(.publishedfileid),\(.time_updated)"')
readarray -t remote_ids < <(<<< "$aligned" awk -F, '{print $1}')
readarray -t remote_times < <(<<< "$aligned" awk -F, '{print $2}')
if [[ ! -f $versions_file ]]; then
logger INFO "No prior versions file found, creating"
update_stamps "$aligned"
#force refresh all mods if versions file was missing
printf "%s\n" "${remote_ids[@]}"
return 0
fi
readarray -t old_ids < <(< $versions_file awk -F, '{print $1}')
readarray -t old_times < <(< $versions_file awk -F, '{print $2}')
declare -A remote_version
declare -A local_version
for((i = 0; i < ${#remote_ids[@]}; ++i)); do
remote_version[${remote_ids[$i]}]=${remote_times[$i]}
done
needs_update=()
for((i=0;i<${#old_ids[@]};i++)); do
local id=${old_ids[$i]}
local time=${old_times[$i]}
if [[ $time != ${remote_version[$id]} ]]; then
logger WARN "Mod '$id' timestamp '$time' != '${remote_version[$id]}'"
needs_update+=($id)
fi
done
printf "%s\n" "${needs_update[@]}"
}
merge_modlists(){
local diff="$1"
_sort(){
printf "%s\n" "$diff"
printf "%s\n" "${needs_update[@]}"
}
readarray -t needs_update < <(check_timestamps)
if [[ -z ${needs_update[@]} ]]; then
echo "$diff"
return 0
fi
if [[ -z "$diff" ]] && [[ ${#needs_update[@]} -gt 0 ]]; then
printf "%s\n" "${needs_update[@]}"
else
# remove duplicates
_sort | sort -u
fi
}
concat_mods(){ concat_mods(){
readarray -t concat_arr <<< "$@" readarray -t concat_arr <<< "$@"
local id local id
@@ -1260,7 +1212,7 @@ launch(){
if [[ $debug -eq 1 ]]; then if [[ $debug -eq 1 ]]; then
local launch_options="$steam_cmd -applaunch $appid -connect=$ip:$gameport -nolauncher -nosplash -name=$name -skipintro -mod=$concat" local launch_options="$steam_cmd -applaunch $appid -connect=$ip:$gameport -nolauncher -nosplash -name=$name -skipintro -mod=$concat"
printf "Debug mode: these options would have been used to launch the game: $launch_options" printf "Debug mode: these options would have been used to launch the game: %s" "$launch_options"
return 0 return 0
fi fi
echo "$concat" > "$_cache_launch" echo "$concat" > "$_cache_launch"
@@ -1296,75 +1248,121 @@ final_handshake(){
printf "\n" printf "\n"
return 6 return 6
} }
manual_mod_install(){ watcher(){
local ip="$1" local -n to_download="$1"
local gameport="$2" local -n signatures="$2"
local diff="$3" local mode="$3"
local sanitized_mods="$4"
local mode="$5"
local appid="$6"
local ex="$state_path/dzg.watcher"
readarray -t stage_mods <<< "$diff" declare -i i=0
[[ -f $ex ]] && rm $ex local remote_time
local length
length=${#to_download[@]}
for mod in "${!to_download[@]}"; do
remote_time=${to_download[$mod]}
[[ -f $ex ]] && return 1
case $mode in
"auto" | "force")
$steam_cmd "steam://url/CommunityFilePage/${mod}+workshop_download_item ${aid} ${mod}"
echo "# Opening workshop page for ${mod}. If you see no progress, you may be out of disk space."
;;
*)
$steam_cmd "steam://url/CommunityFilePage/${mod}"
echo "# Opening workshop page for ${mod}. If you see no progress after subscribing, try unsubscribing and resubscribing again until the download commences."
;;
esac
sleep 1s
foreground
_watcher(){ until [[ -d $downloads_dir/${mod} ]]; do
for((i=0;i<${#stage_mods[@]};i++)); do
[[ -f $ex ]] && return 1 [[ -f $ex ]] && return 1
sleep 0.1s
if [[ $mode == "auto" ]] || [[ $mode == "force" ]]; then # NOTE: fallback for instantaneous downloads
$steam_cmd "steam://url/CommunityFilePage/${stage_mods[$i]}+workshop_download_item $aid ${stage_mods[$i]}" if [[ $mode == "auto" || $mode == "force" ]]; then
echo "# Opening workshop page for ${stage_mods[$i]}. If you see no progress, you may be out of disk space." if [[ -d $workshop_dir/${mod} ]]; then
else
$steam_cmd "steam://url/CommunityFilePage/${stage_mods[$i]}"
echo "# Opening workshop page for ${stage_mods[$i]}. If you see no progress after subscribing, try unsubscribing and resubscribing again until the download commences."
fi
sleep 1s
foreground
until [[ -d $downloads_dir/${stage_mods[$i]} ]]; do
[[ -f $ex ]] && return 1
sleep 0.1s
if [[ -d $workshop_dir/${stage_mods[$i]} ]]; then
break break
fi fi
done
foreground
if [[ $mode == "auto" ]] || [[ $mode == "force" ]]; then
echo "# Steam is downloading ${stage_mods[$i]} (mod $((i+1)) of ${#stage_mods[@]}). You do not need to manually Subscribe."
else
echo "# Steam is downloading ${stage_mods[$i]} (mod $((i+1)) of ${#stage_mods[@]})"
fi fi
until [[ -d $workshop_dir/${stage_mods[$i]} ]]; do
[[ -f $ex ]] && return 1
sleep 0.1s
done
foreground
echo "# ${stage_mods[$i]} moved to mods dir"
done done
echo "100"
}
_watcher > >($steamsafe_zenity --pulsate --progress --auto-close --title="DZG Watcher" --width=500 2>/dev/null; rc=$?; [[ $rc -eq 1 ]] && touch $ex)
if [[ $mode == "force" ]]; then foreground
rm "$versions_file" case $mode in
check_timestamps "auto" | "force")
return 0 echo "# Steam is downloading ${mod} (mod $((i+1)) of ${length}). You do not need to manually Subscribe."
;;
*)
echo "# Steam is downloading ${mod} (mod $((i+1)) of ${length})"
;;
esac
until [[ -d $workshop_dir/${mod} ]]; do
[[ -f $ex ]] && return 1
sleep 0.1s
done
foreground
if [[ ! -v signatures["${mod}"] ]]; then
echo "$mod,$remote_time" >> "$versions_file"
else
sed -i "s/$mod,${signatures[$mod]}/$mod,$remote_time/" "$versions_file"
fi
echo "# ${mod} moved to mods dir"
i+=1
done
echo "100"
}
install_mods(){
local sanitized_mods="$1"
local mode="$2"
local ex="$state_path/dzg.watcher"
[[ -f $ex ]] && rm "$ex"
if [[ -f "$versions_file" ]]; then
readarray -t local_mods < "$versions_file"
else
local_mods=()
fi fi
local diff=$(compare "$sanitized_mods") declare -A mod_signatures
if [[ -z $diff ]]; then local local_id
if [[ $mode == "auto" ]]; then local local_time
rm "$versions_file" for mod in "${local_mods[@]}"; do
check_timestamps IFS="," read -ra fields <<< "$mod"
local_id="${fields[0]}"
local_time="${fields[1]}"
mod_signatures[$local_id]=$local_time
done
readarray -t remote_mods <<< "$sanitized_mods"
declare -A download
local remote_timestamps
local remote_id
local remote_time
remote_timestamps=$(get_timestamps "${remote_mods[@]}")
for mod in $(<<< "$remote_timestamps" jq -r '.response.publishedfiledetails[]|"\(.publishedfileid),\(.time_updated)"'); do
IFS="," read -ra fields <<< "$mod"
remote_id="${fields[0]}"
remote_time="${fields[1]}"
# NOTE: mod is not present in versions file
if [[ ! -v mod_signatures["$remote_id"] ]]; then
download["$remote_id"]=$remote_time
continue
fi fi
launch "$ip" "$gameport" "$sanitized_mods" "$appid" # NOTE: mod timestamp is out of date
else local_time="${mod_signatures["$remote_id"]}"
printf "User aborted download process, or some mods may have failed to download. Try connecting again to resync." if [[ $remote_time != "$local_time" ]]; then
download["$remote_id"]=$remote_time
continue
fi
done
[[ ${#download[@]} -lt 1 ]] && return
if [[ $(check_architecture) -eq 1 ]] && [[ $(test_display_mode) == "gm" ]]; then
printf "Use Desktop Mode to download mods on Steam Deck"
exit 1 exit 1
fi fi
watcher download mod_signatures "$mode" > >($steamsafe_zenity --pulsate --progress --auto-close --title="DZG Watcher" --width=500 2>/dev/null; rc=$?; [[ $rc -eq 1 ]] && touch "$ex")
} }
test_display_mode(){ test_display_mode(){
pgrep -a gamescope | grep -q "generate-drm-mode" pgrep -a gamescope | grep -q "generate-drm-mode"